sharing dictionaries amongst class instances

Francis Avila francisgavila at yahoo.com
Sun Nov 9 17:11:29 EST 2003


"Kerry Neilson" <kmneilso at REMOVEyahoo.com> wrote in message
news:gmxrb.114011$275.322447 at attbi_s53...
> Hi,
> Really hung up on this one.  I'm trying to get all the fields of a
> dictionary to be unique for each class:
>
> class A {
>   my_dict = []
>   dict_entry = { 'key1':0, 'key2':0 }
>
>   __init__(self):
>     for x in range(10):
>           tmp = copy.deepcopy(self.dict_entry)
>           tmp['key1'] = x
>           self.my_dict.append(tmp)
> }

I don't really understand what you're trying to do here, and it doesn't help
that the syntax is completely wrong.  Try pasting directly from real code or
an interactive session in the future, and not trying to ad-lib an email
message.

I assume you mean this (watch me break my own advice):

import copy
class A:
    dictlist = []
    dictlist_elem = { 'key1':0, 'key2':0 }

    def __init__(self):
        for x in range(10):
            tmp = copy.deepcopy(self.dictlist_elem)
            tmp['key1'] = x
            self.dictlist.append(tmp)


Now, this code makes no sense to me without knowing what you want to do.
Init will just keep adding similar dictionaries to dictlist, which are
accessable from all instances.

>>> a = A()
>>> [ D['key1'] for D in a.dictlist]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b = A()
>>> [ D['key1'] for D in a.dictlist]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [ D['key2'] for D in a.dictlist]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Is this what you want?

> in a driver, I have
>
> inst0, inst1 = A.A(), A.A()
> inst0.my_dict[1]['key2'] = "ted"
> inst1.my_dict[5]['key2'] = "steve"
> inst0.display()
> inst1.display()

So, class A is now in a module named A?  And what does A.A.display()
display?  (You didn't include code for that method).

I'll assume that the module detail is insignificant, and that display()
prints dictlist.

> printing them out shows that both objects have ted and steve in their
> dictionaries.

Well, yes.  You declared your dictionary and dictionary lists as class
attributes.  Each instance does a lookup in itself, and not finding
'dictlist' it looks in the class, where it's found.

Ok, this point can often trip people up, so I'll go into more detail. (The
following is for "classic" classes, which are on their way out.  New-style
classes are a bit different wrt instantiation and type.)

In Python, classes are objects.  So when you define class C, what you're
saying is "make a class object which has these attributes and these methods,
and make the name 'C' point to that object."

>>> class C:
...     someint = 12
...     mylist = [1,2,3]
...
>>> C
<class __main__.C at 0x00AC5600>
>>> C.someint
12
>>> C.mylist
[1, 2, 3]
>>>

See? It's a real object with a real location in memory, not just a
"template" for "real" instances.  Classes are just as real as instances.

When you make an instance, Python makes a new object (an instance) and then
calls C.__init__(newinstanceobject).  Init is an instance
configurator--anything done in init is only done in the instance, not in the
class.

Indeed, all instances use the class's methods.  instanceobject.dosomething()
is really C.dosomething(instanceobject) (where C is determined at runtime,
as the derived class which provides the method in question, after
inheritence is taken into consideration).  The "self" you add to each method
object is the stand-in argument which will be the instance itself.

Now, if you don't keep the above in mind, behavior like this becomes
shocking:
>> myinst = C()
>>> myinst2 = C()
>>> myinst.someint
12
>>> myinst.someint = 0
>>> myinst.someint
0
>>> myinst2.someint #Ints work...
12
>>> myinst2.mylist.append(5)
>>> myinst2.mylist
[1, 2, 3, 5]
>>> myinst.mylist #What the?!
[1, 2, 3, 5]
>>> C.mylist #Huh?
[1, 2, 3, 5]

When you do assignment on an instance, you are adding an attribute *to the
instance*, not looking up that attribute in the instance/class hiearchy.
But when you *modify* an attribute, Python *does* look for that attribute,
does find it in the class object, and does modify it in the class object,
*not* in the instance object!

Assignment is fundamentally different from modification.  Assignment makes a
name point to an object.  mylist[2] = 'something' makes the third item in
mylist (an un-named name, if you will) point to 'something'.  But
mylist.dosomething() is radically different!  It changes the object *in
place*.  Just to make a point of how different it is, any in-place
object-modifying method will return None.

> I have done this very thing outside of a class, and it works
> wonderfully.

I don't really know what this would look like outside of a class; I'm not
really sure what "outside of a class" means.

>  All other attributes in the class are able to remain unique.
> ie, inst0.data = 5 and inst1.data = 8 works fine.

Why this happens should make sense now.

> I believe I could set the dictionaries up beforehand, but they will be
> substatially different sizes, and it certainly wouldn't be proper.
>
> Any ideas?  Thanks very much for any insight.

If only the subject of this message were the question, I would answer: "Just
declare the dictionary in the class object of the instances."  However, I
suspect that the question in your mind means a thing different from what it
means to Python, and that you will need to reclarify your problem.

--
Francis Avila





More information about the Python-list mailing list