dictionary containing instances of classes behaving oddly

Erik Johnson ejatsomewhere.com
Thu Dec 28 16:13:06 EST 2006


"Ben" <Benjamin.Barker at gmail.com> wrote in message
news:1167334659.073835.223040 at 73g2000cwn.googlegroups.com...

> Yes- I can see that  my_list and mops, being outside def __init__()
> only get created once, hence the confusion.
>
> Surely def __init__() gets called each time an instance is created
> however? But the snag is that if they have default values set these are
> shared between all instances, even if they are, for instance, lists...?

    I don't think I quite understand the confusion, and I think I might have
said something misleading.  The def statement itself is only executed once,
as are any object initializers contained within it.  Your record.__init__()
is not using a default initializer, and here:

class record:
        my_list =[]
        mops=[]

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


mops as the second argument to __init__ is a formal vairable, not a
reference to record.mops.  If you pass the same list reference to each
constructor, then each record object shares the same list.

You previously said:

 I had thought that then each time I created an instance of the record class
as an element of my dictionary:

self.mop_list[record_number]=record(self.mops[:])

I would create a brand new instance of the record class.It would have a
mops list initialized with mops (because the def__init__ constructor is
called when the class is instantiated), and an empty, individual list
my_list.

I beleive this is basically correct - by using the slice notation in

    self.mops[:]

you are passing a copy of that list as the value. The difference is
demonstrated here:

>>> class Foo:
...   X = [99]
...   def __init__(self, X):  # X is formal variable here, not Foo.X!
...     self.X = X
...
>>> y = [1,2,3]
>>> f1 = Foo(y)
>>> f1.X
[1, 2, 3]
>>> Foo.X
[99]
>>> f1.X.append(42)
>>> f1.X
[1, 2, 3, 42]
>>> y
[1, 2, 3, 42]
>>> Foo.X
[99]
>>> f2 = Foo(y[:])
>>> f2.X
[1, 2, 3, 42]
>>> y
[1, 2, 3, 42]
>>> Foo.X
[99]
>>> f2.X.append('something else')
>>> f2.X
[1, 2, 3, 42, 'something else']
>>> f1.X
[1, 2, 3, 42]
>>> y
[1, 2, 3, 42]
>>> Foo.X
[99]
>>>


    So, I guess I don't see exactly where the problem is, and without all
your source, I am kinda poking in the dark. But from the behaviour observed
in your record objects, you are obviously ending up with shared list
references where you intend to get per-object individual lists.  Generally
the way to do that is to assign a new, empty list in the body of the object
initializer and then populate that list as needed.

Good luck.
-ej





More information about the Python-list mailing list