Re: Need help with simple OOP Python question

2011-09-08 Thread Piet van Oostrum
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

2011-09-05 Thread Kristofer Tengström
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

2011-09-05 Thread Stephen Hansen
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

2011-09-05 Thread Peter Otten
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

2011-09-05 Thread Ben Finney
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

2011-09-05 Thread srinivas hn
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

2011-09-05 Thread Peter Otten
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

2011-09-05 Thread Kristofer Tengström
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

2011-09-05 Thread Jon Clements
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

2011-09-05 Thread Peter Otten
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

2011-09-05 Thread Terry Reedy

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