Reputation:
I'm coding a TreeStructure
(TS) class, which lets me create parent and child objects, which are linked to each other. Every TS -object has m_parent
attribute, which is controlled with parent
property, and also they have children
list, which holds in all the children of this parent. Whenever I add a child to it's parent's children
list, it gets added to it's own children
list too? Here's what I have:
ROOT = "__ROOT__"
class TreeStructure:
def __init__(self, parent=ROOT, children=[]):
self.children = children
self.parent = parent
@property
def parent(self):
'''Returns m_parent'''
if hasattr(self, "m_parent"):
return self.m_parent
else:
return None
@parent.setter
def parent(self, parent=ROOT):
'''Sets m_parent'''
if type(parent) == type(self):
if self.parent:
del self.parent
self.m_parent = parent
self.m_parent.children.append(self)
elif parent == ROOT:
if self.parent:
del self.parent
self.m_parent = ROOT
else:
raise TypeError("Parent's type %s did not match objects type %s"
%(type(parent), type(self)))
@parent.deleter
def parent(self):
'''Deletes m_parent'''
if self.parent:
if self.parent != ROOT:
self.m_parent.children.remove(self)
del self.m_parent
And now by creating two simple objects, it should work. However, it doesn't.
a = TreeStructure()
b = TreeStructure(a)
The problem appears at line 25, self.m_parent.children.append(self)
. If I add print's to both sides of that line, I see that both print(self.m_parent.children)
and print(self.children)
print an empty list []
BEFORE the append line. Now if I add the prints AFTER the append line, both prints will say [<__main__.TreeStructure object at 0x...>]
, which should only happen for the parent, not the child?
Upvotes: 1
Views: 3522
Reputation: 101919
Do not use []
as a default value!
>>> def bad(default=[]):
... default.append(1)
... print default
...
>>> bad()
[1]
>>> bad()
[1, 1]
>>> bad()
[1, 1, 1]
>>> def good(default=None):
... if default is None:
... default = []
... default.append(1)
... print default
...
>>> good()
[1]
>>> good()
[1]
Default arguments are created when the function is defined, not when it is called.
So only use non-mutable types for defaults. using integers, strings, tuples is okay, but if you want a default list or dictionary or anything mutable then use None
and do the above trick.
Read this question and answers for better understanding of this matter.
Upvotes: 5
Reputation: 97571
You've been caught out by old-style classes (which don't support descriptors, such as @property
s). You should be using:
class TreeStructure(object):
After doing that, your code works for me
I'm testing using python 2.7. In 3.x, all classes are new-style.
Upvotes: -2