cannot find object instance

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Thu Aug 28 12:35:42 EDT 2008


jimgardener a écrit :
> hi,
> i am a python newbie..

 From what I can see from your code, you're a newbie to programming in 
general...

> while trying out some message passing between
> two object instances i came across a problem

First point : you have both a circular dependency between ModuleA and 
ModuleB - which is better to avoid unless you really like headaches... 
You mention Java somewhere else, so I assume you have some at least some 
Java background. Point here is that Python is not Java, and doesn't 
restrict you to one ("public") class per module. IOW, if you have two 
strongly related classes (which is obviously the case here), better to 
put both in a same module.

> moduleA.py
> --------------------
> import moduleB
> class MyClassA:
>     def __init__(self):
>         self.age=0
>         self.address=''
>     def createClassB(self):
>         self.objB=moduleB.MyClassB()

Why is this in a distinct method instead of being in the initializer ? 
And why is it named create*Class* when it creates an *instance* ?

>     def validate(self,age,address):
>         if(age >= 100 or address==''):
>             self.age=20;
>             self.address="Broadway,NewYork"
>         self.objB.display(self.age,self.address)
>     def callB(self):
>         self.objB.execute()

Looks like a somewhat messy, circonvoluted and arbitrary 
overcomplexificated control flow...

> if __name__ == "__main__":
>     objA=MyClassA()
>     objA.createClassB()
>     objA.callB()
> 
> moduleB.py
> ------------------
> import moduleA
> 
> class MyClassB:
>     def __init__(self):
>         self.createA()
>     def createA(self):
>         self.objA=moduleA.MyClassA()

You do understand that self.objA won't be the same MyClassA instance as 
the one that instanciated this instance of MyClassB, do you ?

>     def execute(self):
>         self.objA.validate(111,'')
>     def display(self,age,address):
>         print 'displaying:',str(age),address

You don't have to call str on age here.

> 
> when i run the code i get a message
> AttributeError: MyClassA instance has no attribute 'objB'

Indeed.

You first create an instance of MyClassA named objA, call createClassB() 
on it which create an instance of MyClassB referenced by objA.objB.

When objA.objB is created, it itself creates another instance of 
MyClassA referenced by objA.objB.objA, which is totally distinct from 
objA...

Then you call objA.callB(),
which itself call objA.objB.execute(),
which in turn call objA.objB.objA.validate(),
which in turn call objA.objB.objA.objB.display().

But at this point, objA.objB.objA (which, I repeat, is *not* objA) has 
no attribute objB since you didn't call objA.objB.objA.createClassB()...

You could have understood this by yourself, either the way I did 
(mentally tracing program execution) or using a couple print statements 
in your code (to effectively trace program execution), or using the 
debugger...

> Do i have to put a placeholder for objB in __init__ of MyClassA ?
> is that why i get this error?someone please tell me how i can solve
> this?  I tried to put self.objB=None but it didn't work..

<ot>
Trying anything that comes to mind instead of trying to understand how 
things work is a well-known antipattern named "programming by accident". 
The best you can hope from this approach is that, for unknown reasons, 
things accidentally seem to work. Until the day where, for still unknown 
reasons, they either stop working, or it appears they never really 
worked at all.

Needless to say, this approach is a pure waste of time.
</ot>

class ClassA(object):
     def __init__(self, age=0, address=''):
         self.age = age
         self.address = address
         self.b= ClassB(self)

     def validate(self,age,address):
         if(age >= 100 or address==''):
             self.age=20;
             self.address="Broadway,NewYork"
         self.b.display(self.age, self.address)

     def call_b(self):
         self.b.execute()

class ClassB(object):
     def __init__(self, a):
         self.a = a
     def execute(self):
         self.a.validate(111,'')
     def display(self, age, address):
         print 'displaying: %s %s' % (age, address)

if __name__ == "__main__":
     objA=ClassA()
     objA.call_b()


Note that this is still uselessly messy and arbitrary 
overcomplificated... Such a ping-pong between two classes is more often 
than not a design smell.

HTH



More information about the Python-list mailing list