Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python树结构(父级和子级)类,子级被附加到它';她自己的孩子?_Python_Python 3.x_Parent_Parent Child_Tree Structure - Fatal编程技术网

Python树结构(父级和子级)类,子级被附加到它';她自己的孩子?

Python树结构(父级和子级)类,子级被附加到它';她自己的孩子?,python,python-3.x,parent,parent-child,tree-structure,Python,Python 3.x,Parent,Parent Child,Tree Structure,我正在编写一个树结构(TS)类,它允许我创建相互链接的父对象和子对象。每个TS-对象都有m_parent属性,该属性由parent属性控制,并且它们还有子对象列表,该列表保存此父对象的所有子对象。每当我将一个子项添加到它的父项的子项列表中时,它也会被添加到它自己的子项列表中?以下是我所拥有的: ROOT = "__ROOT__" class TreeStructure: def __init__(self, parent=ROOT, children=[]): sel

我正在编写一个
树结构
(TS)类,它允许我创建相互链接的父对象和子对象。每个TS-对象都有
m_parent
属性,该属性由
parent
属性控制,并且它们还有
子对象
列表,该列表保存此父对象的所有子对象。每当我将一个子项添加到它的父项的
子项
列表中时,它也会被添加到它自己的
子项
列表中?以下是我所拥有的:

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
现在通过创建两个简单的对象,它应该可以工作了。然而,事实并非如此

a = TreeStructure()
b = TreeStructure(a)

问题出现在第25行,
self.m\u parent.children.append(self)
。如果我将打印添加到该行的两侧,我会看到
打印(self.m_parent.children)
打印(self.children)
在附加行之前打印一个空列表
[]
。现在,如果我在附加行之后添加打印,两个打印都会显示
[]
,这应该只发生在父级,而不是子级?

您已经被旧式类(不支持描述符,例如
@property
s)所困扰。您应该使用:

class TreeStructure(object):
这样做之后,你的代码对我有效

编辑:
我正在使用Python2.7进行测试。在3.x中,所有类都是新的样式。

不要使用
[]
作为默认值

>>> 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]
默认参数是在定义函数时创建的,而不是在调用函数时创建的。 因此,只能对默认值使用不可变类型。使用整数、字符串、元组是可以的,但是如果您想要一个默认列表、字典或任何可变的东西,那么使用
None
并执行上述技巧


阅读问答,更好地理解这件事。

Woooah我已经使用python很多年了,但不知道这个问题,我从未真正遇到过这个问题。但是,是的,谢谢,我现在聪明多了一英寸:)@Mahi:检测这个问题的方法是通过注意
a.children是b.children==True
是的,我确实检测到了这个问题,只是不明白为什么会发生,现在感觉很愚蠢:PYes,我正在使用3.2.3。那个代码也不应该对你有用。@Mahi:是的,我看到了一个完全不同的问题,
儿童
总是
[]
。添加了Python3.x作为标记,因为它在这里很重要。在“setter”上有一个默认参数没有任何意义,因为它总是用两个参数调用。另外,像
type(parent)==type(self)
这样的检查看起来非常可怕,并且使子类化变得不可能。
isinstance(父级、树状结构)
?甚至是
hasattr(parent,“children”)
。我不太明白你的意思,难道
isinstance(parent,treeststructure)
不会阻止我从treeststructure继承任何类,因为该检查只对超类有效吗?编辑:嗯,刚刚用一个子类测试了它,我的对象是子类的实例,但isinstance(对象,超类)仍然返回true。。。我觉得有点愚蠢。另外,我在这里创建了一个菜单类,我只想将菜单对象添加到其他菜单对象中,而不是树结构,即使菜单是从TS.和
hasattr
中插入的,这将是非常危险的。在这种情况下,我可能会为该检查创建一个单独的方法,如
can\u contain
。在
树状结构中
这将接受任何子类,然后在
菜单中
您可以覆盖它以只接受
菜单
子类。这样,如果您以后创建一个
FancyMenu
类,您就可以将其添加到菜单中,而无需更改此代码。这是一个完美的想法。我还在学习,真的想不出这样的事情:P谢谢你的快速提示:)