Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.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_Pep8 - Fatal编程技术网

“自动”;“根对象”;Python中的检测实现?

“自动”;“根对象”;Python中的检测实现?,python,python-3.x,pep8,Python,Python 3.x,Pep8,假设我有两个这样的类: class Root: def __init__(self): self.children = [] class Child: def __init__(self): # How do I make this attribute (or property if I must change # it to one) automatically reference the root object (if the

假设我有两个这样的类:

class Root:
    def __init__(self):
        self.children = []

class Child:
    def __init__(self):
        # How do I make this attribute (or property if I must change
        # it to one) automatically reference the root object (if the
        # current object is a an item of root.children)
        self.root = ???
因此,我的问题部分已经在代码中,但它需要一些澄清。假设我从类中创建对象,如下所示:

root_obj = Root()
child_obj = Child()
root_obj.children.append(child_obj)

如何使
child\u obj.root
自动检测当前对象存储在
root\u obj
下并引用该对象?这样,如果我以后决定将
child\u obj
存储在一个新对象
另一个\u root\u obj.children
中,则
child\u obj.root
将引用该对象。如果我尝试的方法不可能做到这一点,那么在Python中设计这样一个系统的正确方法是什么?

对象不会跟踪引用它的内容。主要是因为这很少需要,而且会给garabage集合增加很多复杂性。因此,这是一种行为,你必须自己实施

下面的解决方案直接实现了将更新
子项
根的
添加子项
删除子项
方法

class Root:
    def __init__(self):
        self.children = set()

    def add_child(self, child):
        self.children.add(child)
        child.roots.add(self)

    def remove_child(self, child):
        if child in self.children:
            self.children.remove(child)
            child.roots.remove(self)

class Child:
    def __init__(self):
        self.roots = set()

root_obj = Root()
child_obj = Child()

root_obj.add_child(child_obj)

child_obj.roots # {<__main__.Root object at 0x000001FDD5406048>}

root_obj.remove_child(child_obj)

child_obj.roots # set()
类根目录:
定义初始化(自):
self.children=set()
def add_child(self,child):
self.children.add(child)
child.root.add(self)
def移除_子对象(自身、子对象):
如果孩子在self.children中:
self.children.remove(子对象)
child.root.remove(self)
班级儿童:
定义初始化(自):
self.roots=set()
root_obj=root()
child_obj=child()
根对象添加子对象(子对象)
child_obj.roots#{}
根对象删除子对象(子对象)
child_obj.roots#set()

对象不跟踪引用它的内容。主要是因为这很少需要,而且会给garabage集合增加很多复杂性。因此,这是一种行为,你必须自己实施

下面的解决方案直接实现了将更新
子项
根的
添加子项
删除子项
方法

class Root:
    def __init__(self):
        self.children = set()

    def add_child(self, child):
        self.children.add(child)
        child.roots.add(self)

    def remove_child(self, child):
        if child in self.children:
            self.children.remove(child)
            child.roots.remove(self)

class Child:
    def __init__(self):
        self.roots = set()

root_obj = Root()
child_obj = Child()

root_obj.add_child(child_obj)

child_obj.roots # {<__main__.Root object at 0x000001FDD5406048>}

root_obj.remove_child(child_obj)

child_obj.roots # set()
类根目录:
定义初始化(自):
self.children=set()
def add_child(self,child):
self.children.add(child)
child.root.add(self)
def移除_子对象(自身、子对象):
如果孩子在self.children中:
self.children.remove(子对象)
child.root.remove(self)
班级儿童:
定义初始化(自):
self.roots=set()
root_obj=root()
child_obj=child()
根对象添加子对象(子对象)
child_obj.roots#{}
根对象删除子对象(子对象)
child_obj.roots#set()

无法自动检测被追加到列表中

这里有两种方法非常接近。您只需选择一个:

  • 类似ORM的函数

  • 使用Pythonic和
    setter将root分配给child,而不是将child附加到root

  • #1的用法:


    无法自动检测被追加到列表中

    这里有两种方法非常接近。您只需选择一个:

  • 类似ORM的函数

  • 使用Pythonic和
    setter将root分配给child,而不是将child附加到root

  • #1的用法:


    创建一个方法
    add\u child
    ,实现这一点是最简单的方法。。。不如果
    root.children
    是一个列表,那么如果您想使用
    root.children.append
    ,实际上是没有办法的,因为对象不知道它们是否被追加到列表中。我在下面给出了答案,但是,如果您准确地指定了将子项的上一个根分配给另一个根时,您希望子项的上一个根发生什么情况,我可以对其进行改进。创建一个方法
    add\u Child
    ,实现这一点将是最简单的方法。。。不如果
    root.children
    是一个列表,那么如果您想使用
    root.children.append
    ,实际上是没有办法的,因为对象不知道它们是否被追加到列表中。我在下面给出了答案,但是如果您指定了在将子对象的上一个根分配到另一个根时,您希望它发生什么情况,我可以对其进行改进。
    root_obj = Root()
    child_obj = Child()
    
    root_obj.children.append(child_obj)
    root_obj.save()
    
    print(child_obj.root) # <__main__.Root object at 0x05932890>
    
    root_obj = Root()
    child_obj = Child()
    
    child_obj.root = root_obj
    
    print(root_obj.children) # [<__main__.Child object at 0x060578F0>]
    
    class Root:
        def __init__(self):
            self.children = []
            self.__previous_children = []
    
        def save(self):
            diff = [c for c in self.__previous_children if c not in self.children]
            if len(diff) == 0 and len(self.__previous_children) == len(self.children):
                return
            for child in diff:
                child.root = None
            self.__previous_children = self.children.copy()
            for child in self.children:
                child.root = self
    
    class Child:
        def __init__(self):
            self.__root = None
    
        @property
        def root(self):
            return self.__root
    
        @root.setter
        def root(self, root):
            if self.__root == root:
                return
            if self.__root is not None:
                try:
                    self.__root.children.remove(self)
                    self.__root.save()
                except:
                    pass
            self.__root = root
            if root is None:
                return
            if self not in root.children:
                root.children.append(self)
                root.save()