Multiple instances and wrong parental links

ChasBrown cbrown at cbrownsystems.com
Sun Jan 2 00:57:15 EST 2011


On Jan 1, 5:59 pm, Josh English <Joshua.R.Engl... at gmail.com> wrote:
> I have hit yet another wall. I am dynamically creating a class and then creating instances of that class. The class relies on a second class to store a list of objects. (This is simplified from the the original by a factor of about 20. The real program is trying to create a Python object around an XML definition object.)
>
> Here's the code:
>
> ## OPTION ONE for class: ElementList
> ### Not really a list, but a wrapper that behaves like a list
> class ElementList(object):
>     def __init__(self, parent, name):
>         self._parent = parent
>         self._name = name
>
> def MakeWrapper(checker, _addNameAsAttribute = False ):
>
>     ## OPTION TWO for class: ElementList
>     class Wrap(object):
>
>         ## OPTION THREE for class: Elementlist
>
>         def __init__(self, name):
>             self._name = name
>             setattr(Wrap, 'stuff', ElementList(self, 'test'))
>
>     Wrap.__name__= checker.title()
>
>     return Wrap
>
> if __name__ == '__main__':
>
>     Dude = MakeWrapper('Dude')
>     print Dude
>     d1 = Dude('Josh')
>     print d1, d1.stuff
>
>     # creating the second instance changes the behavior of the subclass
>     d2 = Dude('Ben')
>     print d2, d2.stuff
>     print d1.stuff._parent
>     print d2.stuff._parent
>
>     #creating a third instance changes the behavior of all the subclasses
>     d3 = Dude('David')
>     print d3, d3.stuff
>     print d1.stuff._parent, d2.stuff._parent, d3.stuff._parent
>
> ## END CODE
>
> And here is the output:
>
>
>
> <class '__main__.Dude'>
> <__main__.Dude object at 0x00DFB930> <__main__.ElementList object at 0x00DFB950>
> <__main__.Dude object at 0x00DFB730> <__main__.ElementList object at 0x00DFB770>
> <__main__.Dude object at 0x00DFB730>
> <__main__.Dude object at 0x00DFB730>
> <__main__.Dude object at 0x00DFB870> <__main__.ElementList object at 0x00DFB9B0>
> <__main__.Dude object at 0x00DFB870> <__main__.Dude object at 0x00DFB870> <__main__.Dude object at 0x00DFB870>
>
> The 'stuff' attribute is an ElementList object linked back to the parent instance, but every time I create an instance, every instance's 'stuff' links back to the last instance created.
>

If every instance's <whatever> is the same, one guesses that the
<whatever> has a class scope, rather than an instance scope.

> I'm not sure why this is happening, or how to prevent it.
>

It's perfectly predictable; to understand what is happening, compare:

>>> def foo():
        class Bar(object):
            def __init__(self):
                setattr(Bar, 'stuff', {})
        return Bar

>>> Dude = foo()
>>> a = Dude()
>>> b = Dude()
>>> a.stuff['foo'] = 2
>>> b.stuff
{'foo': 2}
>>> c = Dude()
>>> a.stuff
{}

with the behavior (which I think you expected) of:

>>> def foo():
        class Bar(object):
            def __init__(self):
                setattr(self, 'stuff', {})
        return Bar

>>> Dude = foo()
>>> a = Dude()
>>> b = Dude()
>>> a.stuff['foo'] = 2
>>> b.stuff
{}
>>> c = Dude()
>>> a.stuff
{'foo': 2}

Cheers - Chas



More information about the Python-list mailing list