views:

48

answers:

2

Dear All,

Can a python class contain an instance of itself as a data container may look like this?

class A:
    def __init__(self, val):
        self.a = A(val)
        self.val = val

aa = A(2) 
#this will cause RuntimeError: maximum recursion depth exceeded

my purpose is using this class as a data container contain a copy inside if it when it be inited to reduce the deepcopy action. it may used as an "undo" chain give a chance to get the init val's value when it's necessary.

is it possible for such an action?

Thanks

KC

+1  A: 

Well, the class you have in self.a also has self.a, and so furher without an end. I'm not sure I get the purpose of what you are doing, but you might try something like this:

class A:
    def __init__(self, val, copy = True):
        if copy:
            self.a = A(val, False)
        self.val = val
unbeli
+2  A: 

This won't work, for the reason already given:

  1. Python sees A(2) and calls A.__init__.
  2. A.__init__ calls A(val).
  3. A(val) calls A.__init__.
  4. GOTO 2

I assume you're doing this so that you have a log of what val has been; that is, if sometime later you decide that you want val to be 3 instead, you don't throw away the original value 2. How about:

Code

class A( object ):
    self.history = [ ]
    @property
    def val( self ):
        return self.history[ -1 ]

    @val.setter
    def val( self, value ):
        self.history.append( value )

    def __init__( self, val ):
        self.val = val

Explanation

  • A( object ): classes should now inherit from object. Just because, basically.
  • @property: this tells python that every time we ask for A.val, it should call A.val() and return the result. This is a decorator; look up the property builtin function for more information.
  • @val.setter: this is similar to the above, but tells Python that every time we try to assign to A.val it should call the following function instead. Instead of setting A.val, it appends the value to the history list.
katrielalex
thanks, that will be a go for me.
K. C