getter and setter and list appends

D

dasacc22

Hi,

I seem to be having a problem with a list being share across multiple
instantiations of it and dont quite understand why this is happening.

My class looks like this,

class Widget(object):
_parent = None
_children = []

def __init__(self, parent=None):
self.parent = parent

@property
def children(self):
return self._children

@property
def parent(self):
return self._parent

@parent.setter
def parent(self, obj):
if obj:
obj._children.append(self)
self._parent = obj


now if i make instances and attach children like so

a = Widget()
b = Widget(a)
c = Widget(a)
d = Widget(c)

Basically all the objects end up sharing the _children list from `a`
instead of forming something like a tree. Any advice would be greatly
appreciated.

Thanks,
Daniel
 
D

Diez B. Roggisch

dasacc22 said:
Hi,

I seem to be having a problem with a list being share across multiple
instantiations of it and dont quite understand why this is happening.

My class looks like this,

class Widget(object):
_parent = None
_children = []

def __init__(self, parent=None):
self.parent = parent

@property
def children(self):
return self._children

@property
def parent(self):
return self._parent

@parent.setter
def parent(self, obj):
if obj:
obj._children.append(self)
self._parent = obj


now if i make instances and attach children like so

a = Widget()
b = Widget(a)
c = Widget(a)
d = Widget(c)

Basically all the objects end up sharing the _children list from `a`
instead of forming something like a tree. Any advice would be greatly
appreciated.

The problem stems from you confusing instance attributes with class
attributes. You use a latter, which is shared amongst *all* instances of a
given class.

If you want instance-attributes, use

def __init__(self, ..):
self.children = []

also, your use of properties for the children is pointless in Python. Just
use "children" as attribute name. Then, if at one fine day you want to do
something more than just returning that value, you can still do that witout
changing the interface by using a property - as you do so for parent.

Diez
 
D

dasacc22

Ah thank you for clarifying, I did confuse instance and class
attributes from creating the list in the class def. I actually just
spiffed up that class to represent a portion of a much larger class
that needs getter and setter for children. Doing as you said fixed my
problem, heres the code as reference for w/e

class Widget(object):
_children = None
_parent = None

def __init__(self, parent=None):
self.children = []
self.parent = parent

@property
def children(self):
return self._children

@children.setter
def children(self, obj):
self._children = obj

@property
def parent(self):
return self._parent

@parent.setter
def parent(self, obj):
if obj:
print obj
obj.children.append(self)
self._parent = obj


dasacc22 said:
I seem to be having a problem with a list being share across multiple
instantiations of it and dont quite understand why this is happening.
My class looks like this,
class Widget(object):
    _parent = None
    _children = []
    def __init__(self, parent=None):
        self.parent = parent
    @property
    def children(self):
        return self._children
    @property
    def parent(self):
        return self._parent
    @parent.setter
    def parent(self, obj):
        if obj:
            obj._children.append(self)
            self._parent = obj
now if i make instances and attach children like so
a = Widget()
b = Widget(a)
c = Widget(a)
d = Widget(c)
Basically all the objects end up sharing the _children list from `a`
instead of forming something like a tree. Any advice would be greatly
appreciated.

The problem stems from you confusing instance attributes with class
attributes. You use a latter, which is shared amongst *all* instances of a
given class.

If you want instance-attributes, use

def __init__(self, ..):
    self.children = []

also, your use of properties for the children is pointless in Python. Just
use "children" as attribute name. Then, if at one fine day you want to do
something more than just returning that value, you can still do that witout
changing the interface by using a property - as you do so for parent.

Diez
 
T

Terry Reedy

dasacc22 said:
Hi,

I seem to be having a problem with a list being share across multiple
instantiations of it and dont quite understand why this is happening.

Class attributes are shared by all instances.
My class looks like this,

class Widget(object):
_parent = None
_children = []

Move this line
def __init__(self, parent=None):
self.parent = parent

to here.
 
P

Piet van Oostrum

dasacc22 said:
d> Ah thank you for clarifying, I did confuse instance and class
d> attributes from creating the list in the class def. I actually just
d> spiffed up that class to represent a portion of a much larger class
d> that needs getter and setter for children. Doing as you said fixed my
d> problem, heres the code as reference for w/e
d> class Widget(object):
d> _children = None
d> _parent = None

You still have them as class variables here. Now they are only used as
defaults because you assign to them in the instances so the instance
variables will be created then. But I think it is still confusing to
have these class variables here that you never use as such. Maybe this
is some leftover from Java experience where you do declare instance
variables at the class level?
d> def __init__(self, parent=None):
d> self.children = []
d> self.parent = parent
d> @property
d> def children(self):
d> return self._children
d> @children.setter
d> def children(self, obj):
d> self._children = obj

What is the added value of using a property for the children attribute?
Why not just use an instance variable directly? Also a Java inheritance?
 
D

dasacc22

d> Ah thank you for clarifying, I did confuse instance and class
d> attributes from creating the list in the class def. I actually just
d> spiffed up that class to represent a portion of a much larger class
d> that needs getter and setter for children. Doing as you said fixed my
d> problem, heres the code as reference for w/e
d> class Widget(object):
d>     _children = None
d>     _parent = None

You still have them as class variables here. Now they are only used as
defaults because you assign to them in the instances so the instance
variables will be created then. But I think it is still confusing to
have these class variables here that you never use as such. Maybe this
is some leftover from Java experience where you do declare instance
variables at the class level?
d>     def __init__(self, parent=None):
d>         self.children = []
d>         self.parent = parent
d>     @property
d>     def children(self):
d>         return self._children
d>     @children.setter
d>     def children(self, obj):
d>         self._children = obj

What is the added value of using a property for the children attribute?
Why not just use an instance variable directly? Also a Java inheritance?

Hi, yes, you are right, this is from previous experience, and thank
you for bringing this out. It would be better suited to move those
class variables to a comment to stay comfortable perhaps or eliminate
them altogether.

The property method of parent and children actually calls a
_set_as_parent() and _set_as_child() method after setting the private
variable to pack the object for display purposes so that children can
be detached from the parent (becoming its own parent) as a gui event.
 
P

Piet van Oostrum

dasacc22 said:
d> The property method of parent and children actually calls a
d> _set_as_parent() and _set_as_child() method after setting the private
d> variable to pack the object for display purposes so that children can
d> be detached from the parent (becoming its own parent) as a gui event.

Oh, I saw that in the parent setter but not in the children setter.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,292
Messages
2,571,494
Members
48,178
Latest member
SusanaHam4

Latest Threads

Top