Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/356.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/python-3.x/15.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_Loops_Class - Fatal编程技术网

Python 相互调用的函数中的循环

Python 相互调用的函数中的循环,python,python-3.x,loops,class,Python,Python 3.x,Loops,Class,我有一个类代表一个家庭中的一个人(FamilyMember) 我实现了函数setParent,该函数接收FamilyMember对象并将其添加到当前对象的parent列表中。 在setChild函数中执行的操作与此完全相同 def setParent(self, parent): if not isinstance(parent, FamilyMember): raise TypeError("Parent must be set to a Fam

我有一个类代表一个家庭中的一个人(FamilyMember)

我实现了函数
setParent
,该函数接收FamilyMember对象并将其添加到当前对象的
parent
列表中。 在
setChild
函数中执行的操作与此完全相同

    def setParent(self, parent):
        if not isinstance(parent, FamilyMember):
            raise TypeError("Parent must be set to a FamilyMember")
        if parent in self.parents:
            print("parent already in the list")
            return
        self.parents.append(parent) 
        parent.setChild(self)


    def setChild(self, child):

        if not isinstance(child, FamilyMember):
            raise TypeError("child must be set to a FamilyMember")
        if child in self.children:
            print("child already in the list")
            return
        self.children.append(child) 
        child.setParent(self)
问题:当一个函数调用另一个函数时(如果我们设置当前对象的父对象,我们也应该将当前对象设置为父对象的子对象),它们进入一个循环。=>我设法阻止它检查对象是否已经在列表中。但这意味着我总是对函数进行不必要的调用

    def setParent(self, parent):
        if not isinstance(parent, FamilyMember):
            raise TypeError("Parent must be set to a FamilyMember")
        if parent in self.parents:
            print("parent already in the list")
            return
        self.parents.append(parent) 
        parent.setChild(self)


    def setChild(self, child):

        if not isinstance(child, FamilyMember):
            raise TypeError("child must be set to a FamilyMember")
        if child in self.children:
            print("child already in the list")
            return
        self.children.append(child) 
        child.setParent(self)
我不喜欢的可能解决方案:我可以再做两个相同的函数,但不调用另一个函数。但这意味着重复代码,并具有4个不同的函数,这不是一个好的实践。 例:

我不喜欢的可能解决方案:我将另一个函数的代码重写为两个函数。这同样是在重写代码,但并不十分优雅:

    def setParent_no_loop(self, parent):
        if not isinstance(parent, FamilyMember):
            raise TypeError("Parent must be set to a FamilyMember")
        if parent in self.parents:
            print("parent already in the list")
            return
        self.parents.append(parent)
        parent.children.append(self) 

问题是,你能找到一个优雅的方法来解决这个问题吗?

我建议设计如下方法:

def add_child(self,child):
self.children.append(子级)
child.parents.append(self)
def添加_父项(自身、父项):
父项。添加子项(自)

这些方法不需要是递归的或相互递归的。根据需要添加您自己的错误处理代码。

您可以对对象进行散列,并通过set函数开头的散列比较检查它们是否存在于另一个对象中?下面我已经这样做了(因为如果用户忘记先进行比较,这是最安全的),但是您也可以在调用set函数之前进行比较,以避免额外的函数调用

类家族成员(对象):
定义初始化(自):
self.relations=set()
self.hashval=hash(self)
self.parents=set()
self.children=set()
def knowsAbout(自身、其他散列):
如果在自我关系中发生冲突:
返回真值
其他:
返回错误
def setParent(self,newParent):
如果不是自知(新家长):
self.relations.add(newParent.hashval)
self.parents.add(newParent)
newParent.addChild(self)
def setChild(self,newChild):
如果不是自己知道的(新孩子):
self.relations.add(newChild.hashval)
self.children.add(newChild)
newChild.addParent(self)

这仍然是一个额外的函数调用,但哈希比较至少是一个快速的比较。

父项
子项
设置为集合而不是列表

然后,在每种方法中,只需添加,不必担心

def setParent(self, parent):
    if not isinstance(parent, FamilyMember):
        raise TypeError("Parent must be set to a FamilyMember")
    self.parents.add(parent) 
    parent.children.add(self)


def setChild(self, child):
    if not isinstance(child, FamilyMember):
        raise TypeError("child must be set to a FamilyMember")
    self.children.add(child) 
    child.parents.add(self)

我设法阻止它检查对象是否已经在列表中。
-这是一个优雅的解决方案。在添加之前检查成员是否已经在列表中并没有什么错,您应该将此作为该功能的安全特性来执行。如果确实要避免函数调用(这不是主要的性能损失),可以检查
如果self不在parent.children
中,然后调用
parent.setChild(self)
(对于setParent示例).由于您提到的第一种方法确实打印列表中已有的父/子项,因此您可以简单地删除该打印语句,这样每次添加父/子项时都不会感到高兴。如果要进行这种错误检查,只需返回一个布尔值即可。这样,如果需要,您可以选择检查。
优雅
可以是主观的,什么会让您满意?这是可行的,但在添加之前,我仍然会检查列表中是否存在家长或孩子。这样的检查是最低限度的,并促进了类型安全。是的,当然。我确实说过,您应该根据需要添加自己的错误处理代码。除非所有散列值都是不同的,否则这将无法正常工作,因为您只是存储散列并检查散列是否相同。最好实现
\uuuuu hash\uuuu
\uuuuu eq\uuuu
方法,并将对象本身存储在集合中。或者,您可以将对象ID存储在集合中,而不是它们的哈希
id(self)
保证是唯一且不变的,因此您甚至不需要向对象添加字段。