A problem with some OO code.

TPJ tprimke at interia.pl
Sat Feb 4 07:21:50 EST 2006


Help me please, because I really don't get it. I think it's some stupid
mistake I make, but I just can't find it. I have been thinking about it
for three days so far and I still haven't found any solution.

My code can be downloaded from here:
http://www.tprimke.net/konto/PyObject-problem.tar.bz2. There are some
scripts for GNU/Linux system (bash to be precise).

All you need to know is that there are four classes. (Of course, you
may generate all the documentation by typing just "./make_docs". All
you need is Python with Epydoc installed.)

In the PyObject.py there are two classes: Object and OManager. When
Object wants to know if some link is safe (in another words: it wants
to know if some another object exists), it calls the proper method of
its objects' manager (the OManager instance). Details are not important
here, so I'll just say, that if the link is safe, the objects' manager
calls the proper method of the object, that sent him request. This
method of the object just stores the information about that link (that
it's safe), in the so-called private field (the fields used to store
the information about the links are called __ls_existing_links and
__ls_demanded_links).

And now the tests. In the test.py file this is a class called Obj. That
class is just an Object. This is also a class called System1 - this
class is used only to create a more complex system composed of many
objects and one objects' manager.

You can run all the tests by just typing "./test" in console (or a
terminal emulator). I'm still getting the same error:

--------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 142, in test04CreateSystems
    system1 = System1()
  File "test.py", line 81, in __init__
    self.objA.demandNewLink( 'B' )
  File "/home/tpj/opt/Praca/Programy/PyObject/workdir/PyObject.py",
line 503, in demandNewLink
    s_object )
  File "/home/tpj/opt/Praca/Programy/PyObject/workdir/PyObject.py",
line 800, in _makeNewLink
    o_srcobj._makeLinkSafe( s_target )
  File "/home/tpj/opt/Praca/Programy/PyObject/workdir/PyObject.py",
line 608, in _makeLinkSafe
    self.__makeLinkSafe( s_object )
  File "/home/tpj/opt/Praca/Programy/PyObject/workdir/PyObject.py",
line 582, in __makeLinkSafe
    i = self.__ls_demanded_links.index( s_object )
AttributeError: 'Obj' object has no attribute
'_Object__ls_demanded_links'
--------------------------------------------------

Perhaps I'll explain what's going on there. First, the objects' manager
is created, and then also some objects are created. After doing that,
the object called "objA" demands a new link to the other object, called
"objB" (this is the line 81 in the error message above). As the result,
the "demandNewLink" method of the object "objA" is called. This method
calls the "_makeNewLink" method of the objects' manager, and this
method calls the "_makeLinkSafe" method of the object, that demanded a
new link. The last method, called "__makeNewLink" (so this is a
so-called private method), is called then. This last method is supposed
to check if the link was really demanded and then make it "safe" by
placing the information about this link in the proper dictionary
(__ls_existing_links).

All these methods are the methods of the Object class (defined in
PyObject.py), not of the Obj class (defined in test.py). According to
my knowledge about the OO programming Python should be able to realize,
that the so-called private fields, that are being referred from these
Object class methods, are the private fields of the *Obj class
instance*, not of the *Object class one*.

I even wrote a simple program to test the usage of the so-called
private fields in Python classes:

--------------------------------------------------
class A( object ):
  def __init__( self ):
    self.__a = 1
  def _add( self ):
    print "self.__a =", self.__a
    self.__a += 1
  def print_a( self ):
    print self.__a

class B( A ):
  def __init__( self ):
    A.__init__( self )
    self.__b = 2
  def print_b( self ):
    print self.__b

def test():
  o = B()
  o.print_a()
  o.print_b()
  o._add()
  o.print_a()
  o.print_b()
--------------------------------------------------

The code works just as I thought it should work: all is fine here. The
B class instance (the b object) is able to refer to the so-called
private field of the A class (through a A-class method, that was
inherited by the class B).

Why I can't do the same thing in test.py and in PyObject.py?

I just don't get it.

(And sorry for the subject of this topic. I really had no better
idea...)




More information about the Python-list mailing list