Re: Need help with simple OOP Python question
Terry Reedy tjre...@udel.edu writes: Indexing objects by their internal id is usually useless. obj.id is not the internal id. -- Piet van Oostrum p...@vanoostrum.org WWW: http://pietvanoostrum.com/ PGP key: [8DAE142BE17999C4] -- http://mail.python.org/mailman/listinfo/python-list
Need help with simple OOP Python question
Hi, I'm having trouble creating objects that in turn can have custom objects as variables. The code looks like this: - class A: sub = dict() def sub_add(self, cls): obj = cls() self.sub[obj.id] = obj class B(A): id = 'inst' base = A() base.sub_add(B) base.sub['inst'].sub_add(B) print # prints a blank line print base.sub['inst'] print base.sub['inst'].sub['inst'] -- Now, what I get from this is the following: __main__.B instance at 0x01FC20A8 __main__.B instance at 0x01FC20A8 Why is this? What I want is for them to be two separate objects, but it seems like they are the same one. I've tried very hard to get this to work, but as I've been unsuccessful I would really appreciate some comments on this. I'm sure it's something really easy that I just haven't thought of. Python version is 2.6.5 (I'm using Panda3D to create a 2½D game). -- http://mail.python.org/mailman/listinfo/python-list
Re: Need help with simple OOP Python question
On 9/4/11 11:47 PM, Kristofer Tengström wrote: Hi, I'm having trouble creating objects that in turn can have custom objects as variables. The code looks like this: - class A: sub = dict() You are sharing this single sub dictionary with all instances of your A class. If you want to define instance-specific attributes, define them in the __init__ method, like so: class A: def __init__(self): self.sub = dict() def sub_add(self, cls): obj = cls() self.sub[obj.id] = obj -- Stephen Hansen ... Also: Ixokai ... Mail: me+list/python (AT) ixokai (DOT) io ... Blog: http://meh.ixokai.io/ signature.asc Description: OpenPGP digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: Need help with simple OOP Python question
Kristofer Tengström wrote: Hi, I'm having trouble creating objects that in turn can have custom objects as variables. The code looks like this: - class A: sub = dict() Putting it into the class like this means sub is shared by all instances. def sub_add(self, cls): obj = cls() self.sub[obj.id] = obj class B(A): id = 'inst' base = A() base.sub_add(B) base.sub['inst'].sub_add(B) print # prints a blank line print base.sub['inst'] print base.sub['inst'].sub['inst'] -- Now, what I get from this is the following: __main__.B instance at 0x01FC20A8 __main__.B instance at 0x01FC20A8 Why is this? What I want is for them to be two separate objects, but it seems like they are the same one. I've tried very hard to get this to work, but as I've been unsuccessful I would really appreciate some comments on this. I'm sure it's something really easy that I just haven't thought of. Your class A needs an initialiser: class A: def __init__(self): self.sub = {} # one dict per instance # ... -- http://mail.python.org/mailman/listinfo/python-list
Re: Need help with simple OOP Python question
Kristofer Tengström krille...@gmail.com writes: Hi, I'm having trouble creating objects that in turn can have custom objects as variables. That terminology is rather confused. I think what you want is to have instances with their own attributes. class A: sub = dict() This binds a single object (a new empty dict) to the class attribute ‘sub’. Every instance of class ‘A’ will share the same attribute, and hence that same dict. def sub_add(self, cls): This defines a function which will be bound to the class attribute ‘sub_add’. It will, when later called as a method, receive the instance as the first parameter, bound to the local name ‘self’. obj = cls() self.sub[obj.id] = obj Here, ‘self’ will be an instance of the ‘A’ class. Each instance has no ‘sub’ attribute, so Python will find the class attribute ‘A.sub’, shared by all ‘A’ instances. You're then modifying that class attribute ‘A.sub’. […] Now, what I get from this is the following: __main__.B instance at 0x01FC20A8 __main__.B instance at 0x01FC20A8 Why is this? I hope the above explains it. What I want is for them to be two separate objects, but it seems like they are the same one. Yes. Anything you talk about in the class definition scope cannot know about any instance of that class, since the instances don't exist yet. Instead, instance attributes need to be bound to a particular instance, which means you need to have a reference to the instance; that's what ‘self’ is for. The class initialiser is a method named ‘__init__’, and is called on each newly-created instance before that instance is returned from the constructor. I advise you to work through the Python tutorial, beginning to end, which will give you a good grounding in these and other fundamental Python topics URL:http://docs.python.org/tutorial/. Work through each example, understand it by experimenting, and then proceed to the next, until you've done the lot. -- \ “If history and science have taught us anything, it is that | `\ passion and desire are not the same as truth.” —E. O. Wilson, | _o__) _Consilience_, 1998 | Ben Finney -- http://mail.python.org/mailman/listinfo/python-list
Re: Need help with simple OOP Python question
Hi, You are getting same object because you are overriding the dictionary update. Its printing the proper value with the last updated instance of B. If you want to see the two different instances of class B give print self.sub inside the sub_add method in class A. CHEERS CNA 9986229891 On Mon, Sep 5, 2011 at 12:17 PM, Kristofer Tengström krille...@gmail.comwrote: Hi, I'm having trouble creating objects that in turn can have custom objects as variables. The code looks like this: - class A: sub = dict() def sub_add(self, cls): obj = cls() self.sub[obj.id] = obj class B(A): id = 'inst' base = A() base.sub_add(B) base.sub['inst'].sub_add(B) print # prints a blank line print base.sub['inst'] print base.sub['inst'].sub['inst'] -- Now, what I get from this is the following: __main__.B instance at 0x01FC20A8 __main__.B instance at 0x01FC20A8 Why is this? What I want is for them to be two separate objects, but it seems like they are the same one. I've tried very hard to get this to work, but as I've been unsuccessful I would really appreciate some comments on this. I'm sure it's something really easy that I just haven't thought of. Python version is 2.6.5 (I'm using Panda3D to create a 2½D game). -- http://mail.python.org/mailman/listinfo/python-list -- http://mail.python.org/mailman/listinfo/python-list
Re: Need help with simple OOP Python question
Kristofer Tengström wrote: Thanks everyone, moving the declaration to the class's __init__ method did the trick. Now there's just one little problem left. I'm trying to create a list that holds the parents for each instance in the hierarchy. This is what my code looks like now: - class A: def __init__(self, parents=None): self.sub = dict() if parents: You should explicitly test for None here; otherwise in a call like ancestors = [] a = A(anchestors) the list passed as an argument will not be used, which makes fore confusing behaviour. self.parents = parents else: self.parents = [] def sub_add(self, cls): hierarchy = self.parents hierarchy.append(self) Here you are adding self to the parents (that should be called ancestors) and pass it on to cls(...). Then -- because it's non-empty -- it will be used by the child, too, and you end up with a single parents list. obj = cls(hierarchy) self.sub[obj.id] = obj While the minimal fix is to pass a copy def sub_add(self, cls): obj = cls(self.parents + [self]) self.sub[obj.id] = obj I suggest that you modify your node class to keep track only of the direct parent instead of all ancestors. That makes the implementation more robust when you move a node to another parent. -- http://mail.python.org/mailman/listinfo/python-list
Re: Need help with simple OOP Python question
Thanks everyone, moving the declaration to the class's __init__ method did the trick. Now there's just one little problem left. I'm trying to create a list that holds the parents for each instance in the hierarchy. This is what my code looks like now: - class A: def __init__(self, parents=None): self.sub = dict() if parents: self.parents = parents else: self.parents = [] def sub_add(self, cls): hierarchy = self.parents hierarchy.append(self) obj = cls(hierarchy) self.sub[obj.id] = obj class B(A): id = 'inst' base = A() base.sub_add(B) base.sub['inst'].sub_add(B) print print vars(base) print print vars(base.sub['inst']) print print vars(base.sub['inst'].sub['inst']) - The output from this program is the following: {'parents': [__main__.A instance at 0x02179468, __main__.B instance at 0x021794B8], 'sub': {'inst': __main__.B instance at 0x021794B8}} {'parents': [__main__.A instance at 0x02179468, __main__.B instance at 0x021794B8], 'sub': {'inst': __main__.B instance at 0x021794E0}} {'parents': [__main__.A instance at 0x02179468, __main__.B instance at 0x021794B8], 'sub': {}} As you can see, the problem looks similar to the one before: All the instances have an identical parent list. However, I don't understand why as self.parents is declared in the __init__ method. Any ideas? What I want is for the first instance to have an empty list, the second to have one element in the list and the third to have two parent elements. -- http://mail.python.org/mailman/listinfo/python-list
Re: Need help with simple OOP Python question
On Sep 5, 3:43 pm, Peter Otten __pete...@web.de wrote: Kristofer Tengström wrote: Thanks everyone, moving the declaration to the class's __init__ method did the trick. Now there's just one little problem left. I'm trying to create a list that holds the parents for each instance in the hierarchy. This is what my code looks like now: - class A: def __init__(self, parents=None): self.sub = dict() if parents: You should explicitly test for None here; otherwise in a call like ancestors = [] a = A(anchestors) the list passed as an argument will not be used, which makes fore confusing behaviour. self.parents = parents else: self.parents = [] def sub_add(self, cls): hierarchy = self.parents hierarchy.append(self) Here you are adding self to the parents (that should be called ancestors) and pass it on to cls(...). Then -- because it's non-empty -- it will be used by the child, too, and you end up with a single parents list. obj = cls(hierarchy) self.sub[obj.id] = obj While the minimal fix is to pass a copy def sub_add(self, cls): obj = cls(self.parents + [self]) self.sub[obj.id] = obj I suggest that you modify your node class to keep track only of the direct parent instead of all ancestors. That makes the implementation more robust when you move a node to another parent. I may not be understanding the OP correctly, but going by what you've put here, I might be tempted to take this kind of stuff out of the class's and using a graph library (such as networkx) - that way if traversal is necessary, it might be a lot easier. But once again, I must say I'm not 100% sure what the OP wants to achieve... Jon. -- http://mail.python.org/mailman/listinfo/python-list
Re: Need help with simple OOP Python question
Jon Clements wrote: I must say I'm not 100% sure what the OP wants to achieve... Learn Python? ;) -- http://mail.python.org/mailman/listinfo/python-list
Re: Need help with simple OOP Python question
On 9/5/2011 9:15 AM, Kristofer Tengström wrote: Thanks everyone, moving the declaration to the class's __init__ method did the trick. Now there's just one little problem left. I'm trying to create a list that holds the parents for each instance in the hierarchy. This is what my code looks like now: - class A: def __init__(self, parents=None): self.sub = dict() if parents: self.parents = parents else: self.parents = [] def sub_add(self, cls): hierarchy = self.parents hierarchy.append(self) obj = cls(hierarchy) self.sub[obj.id] = obj Indexing objects by their internal id is usually useless. Considier whether you should be using sets rather than dicts. -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list