By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
439,972 Members | 1,454 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 439,972 IT Pros & Developers. It's quick & easy.

sharing dictionaries amongst class instances

P: n/a
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)
}

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()

printing them out shows that both objects have ted and steve in their
dictionaries. I have done this very thing outside of a class, and it works
wonderfully. All other attributes in the class are able to remain unique.
ie, inst0.data = 5 and inst1.data = 8 works fine.
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.

Jul 18 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
Kerry Neilson wrote:
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)
}


class A { ... } is *not* Python. Are you converting from Java :-) ?
From what follows, I conclude that you want the dicitonary to be unique for
each *instance* (if you want it unique for the class, you are already
there). Unlike Java, you must put it in the constructor then (untested):

class A:
def __init__(self):
self.my_dict = {"key1": 0, "key2": 0}

Dictionaries are the {} thingies, [] indicate list literals. Deepcopy should
be buried very deep in the documentation, where no newbie will ever find
it...
Seriously, take the time to read the excellent tutorial that comes with
Python, and only then try to clean up this mess.

Peter

Jul 18 '05 #2

P: n/a
On Sunday 09 Nov 2003 8:22 pm, Kerry Neilson wrote:
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)
}

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()

printing them out shows that both objects have ted and steve in their
dictionaries. I have done this very thing outside of a class, and it works
wonderfully. All other attributes in the class are able to remain unique.
ie, inst0.data = 5 and inst1.data = 8 works fine.
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.


Kerry,

two observations:

1) That's not proper Python! ;-) and 2) I think the behaviours you want are
only available in 'new style' classes, i.e. classes based upon 'object'. Did
you mean:

---8<---
class A(object):
my_dict = []
dict_entry = { 'key1':0, 'key2':0 }

def __init__(self):
for x in range(10):
tmp = copy.deepcopy(self.dict_entry)
tmp['key1'] = x
self.my_dict.append(tmp)
---8<---

A.my_dict is a /class variable/, i.e. it is tied to the class, not the
instance - there's only one of them, viz:

---8<---
inst0,inst1=A(),A()
id(inst0),id(inst1) # get the id of the instances: (1083256236, 1083254732) id(inst0.my_dict),id(inst1.my_dict) # and the id of their my_dict lists: (1083253228, 1083253228) inst0.my_dict is inst1.my_dict True

---8<---

If you move the initial assignment of my_dict into the __init__() procedure,
and call it self.my_dict() instead, then you'll get a new instance of a list
each time - maybe this is what you want. BTW, is there any particular reason
for choosing the word 'my_dict' to describe a list?

hope this helps you arrive at a solution ;-)

-andyj
Jul 18 '05 #3

P: n/a
> class A { ... } is *not* Python. Are you converting from Java :-) ?
From what follows, I conclude that you want the dicitonary to be unique for each *instance* (if you want it unique for the class, you are already
there). Unlike Java, you must put it in the constructor then (untested):

class A:
def __init__(self):
self.my_dict = {"key1": 0, "key2": 0}

Dictionaries are the {} thingies, [] indicate list literals. Deepcopy should be buried very deep in the documentation, where no newbie will ever find
it...
Seriously, take the time to read the excellent tutorial that comes with
Python, and only then try to clean up this mess.

hmm ... I didnt' word this quite right. I want a list [] of dictionaries
{}. I mean for it to be similar to an array of structs in C, only using a
dictionary instead of a struct and a list instead of an array. Seem
reasonable?

I have read the entire tutorial as well as "Learning Python" in its utter
entirety. This is precisely how I know of deepcopy. I noticed that when I
appended dictionaries to my list, modifying one modifed them all. I want
each entry to be unique. I don't see how to do this without deepcopy. What
really confuses me is that this same scenario works when not embedded in a
class.

As for your suggestion, putting the dictionary initialization and the list
in the contructor did the trick. I had this:

class a:
x = 0
y = 0
:

I suppose it's a c++ leftover thing, thinking i had to declare before I
init. I don't yet understand why it's different for a simple data type than
it is for the list of dictionaries. But by taking the dict_entry{} and
my_dict[] out of the top of the class, it works without deepcopy. Thanks
for the help.
Jul 18 '05 #4

P: n/a


Kerry,

two observations:

1) That's not proper Python! ;-) and 2) I think the behaviours you want are
only available in 'new style' classes, i.e. classes based upon 'object'. Did
you mean:

---8<---
class A(object):
my_dict = []
dict_entry = { 'key1':0, 'key2':0 }

def __init__(self):
for x in range(10):
tmp = copy.deepcopy(self.dict_entry)
tmp['key1'] = x
self.my_dict.append(tmp)
---8<---

A.my_dict is a /class variable/, i.e. it is tied to the class, not the
instance - there's only one of them, viz:

---8<---
inst0,inst1=A(),A()
id(inst0),id(inst1) # get the id of the instances: (1083256236, 1083254732) id(inst0.my_dict),id(inst1.my_dict) # and the id of their my_dict lists: (1083253228, 1083253228) inst0.my_dict is inst1.my_dict True

---8<---

If you move the initial assignment of my_dict into the __init__() procedure,
and call it self.my_dict() instead, then you'll get a new instance of a list
each time - maybe this is what you want. BTW, is there any particular
reason
for choosing the word 'my_dict' to describe a list?

hope this helps you arrive at a solution ;-)

Thanks for the reply, Andy.
Your observation was correct, as I also learned from Peter, and moving the
initial assignment into __init__ is whta I wanted. I guess I didn't realize
that one could do that, being more familiar with c++. And no, calling a
list my_dict was pure accident. Perhaps my explanation in response to Peter
explains it a bit better.

Thanks.
Jul 18 '05 #5

P: n/a

"Kerry Neilson" <km******@REMOVEyahoo.com> wrote in message
news:gmxrb.114011$275.322447@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

Jul 18 '05 #6

P: n/a
> See? The old value seems to reappear. When you say a.x and there is no
instance attribute, Python looks up the class attribute with the same name. So you can use the class attribute as a kind of default value for the
instance attribute.
But beware, this technique bites you as soon as you try it with mutables:
a.y["key"] = "value"
This looks the same, whether y is an instance or class attribute, and you
would not complicate client code with some detection scheme.
A.y {'key': 'value'}

Oops, there was no y attribute in the instance, so we inadvertently

changed y of the underlying class.


Thank you. Your message really cleared a lot of things up for me.
Jul 18 '05 #7

P: n/a
On Sun, 09 Nov 2003 20:22:36 GMT, "Kerry Neilson" <km******@REMOVEyahoo.com> wrote:
Hi,
Really hung up on this one. I'm trying to get all the fields of a
dictionary to be unique for each class:
Please post something that at least compiles
class A {

File "<stdin>", line 1
class A {
^
SyntaxError: invalid syntax

class A { ^--this must be left over from some abortive experiment 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)
}

in a driver, I have

inst0, inst1 = A.A(), A.A() This looks like you are not showing an import A, assuming that class A is defined in A.py
inst0.my_dict[1]['key2'] = "ted"
inst1.my_dict[5]['key2'] = "steve"
inst0.display()
inst1.display()

printing them out shows that both objects have ted and steve in their I suggest you copy and paste from the session where you did that. Otherwise
you're wasting your time and everyone else's.
dictionaries. I have done this very thing outside of a class, and it works
wonderfully. All other attributes in the class are able to remain unique. The above doesn't work period, so there is no telling what you actually did,
and I might be able to guess what you are trying to do, but I don't really want to, sorry.
ie, inst0.data = 5 and inst1.data = 8 works fine.
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.

See above, guess I need a snack ;-)

Regards,
Bengt Richter
Jul 18 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.