“自动”;“根对象”;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()
无法自动检测被追加到列表中
这里有两种方法非常接近。您只需选择一个:
setter将root分配给child,而不是将child附加到root
无法自动检测被追加到列表中 这里有两种方法非常接近。您只需选择一个:
setter将root分配给child,而不是将child附加到root
创建一个方法
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()