Python - 如何编写更高效的Pythonic减少?

Mik*_*and 10 python algorithm tree graph

我正在尝试构建一个非常轻量级的Node类,作为基于Python的层次结构搜索工具.请参阅以下定义.

from functools import reduce
from operator import or_


class Node:

    def __init__(self, name):
        self.name = name
        self.children = []

    def add_child(self, child_node):
        self.children.append(child_node)

    def contains(self, other_node):
        if self == other_node:
            return True
        elif other_node in self.children:
            return True
        else:
            return reduce(or_, [child.contains(other_node)
                                for child in self.children], False)

    def is_contained_by(self, other_node):
        return other_node.contains(self)

    def __eq__(self, other_node):
        return self.name == other_node.name

    def __de__(self, other_node):
        return self.name != other_node.name
Run Code Online (Sandbox Code Playgroud)

contains似乎是函数式编程的教科书案例(直接从" 为什么功能编程事项"中提取).

问题:是否有更高效或Pythonic的写作方式contains?我知道这map通常被列表理解所取代,但我还没有看到更好的reduce基于做递归的方法.

谢谢,

麦克风

===已经编辑...这里的REDONE课程考虑了答案和评论===

class Node:

    def __init__(self, name):
        self.name = name
        self.children = []

    def add_child(self, child_node):
        # Hattip to lazyr for catching this.
        if self.contains(child_node) or child_node.contains(self):
            raise TreeError('A relationship is already defined.')    
        else:
            self.children.append(child_node)                

    def contains(self, other_node):
        # Hattip to lazyr for pointing out any() and to Jochen Ritzel for
        # eliminating the silly child check.
        return (self == other_node or
                any(child.contains(other_node) for child in self.children))

    def is_contained_by(self, other_node):
        return other_node.contains(self)

    def __eq__(self, other_node):
        return self.name == other_node.name

    def __de__(self, other_node):
        return self.name != other_node.name

    def __repr__(self):
        return self.name
Run Code Online (Sandbox Code Playgroud)

Lau*_*low 5

我认为(未经测试)你reduce应该使用any这样的,这将在第一次击中时停止:

return any(child.contains(other_node) for child in self.children)
Run Code Online (Sandbox Code Playgroud)

顺便说一句,你的意思是用于a.contains(b)返回Falsea == blen(a.children) > 0

编辑:如果您的树包含一个循环,如下所示:

a = Node("a")
b = Node("b")
a.add_child(a)
a.add_child(b)
Run Code Online (Sandbox Code Playgroud)

然后

a.contains(b)
Run Code Online (Sandbox Code Playgroud)

会破坏程序.您可能需要在内部contains或内部检查add_child,具体取决于您最常使用的内容.

  • 我很确定一旦图形包含一个循环,它就不再是一棵树了.如果这个结构应该代表一棵树,那么我会检查add_child中的循环 (4认同)
  • 整个`contains`函数可以写成`return self == other_node或any(child.contains(other_node)for child in self.children)`. (3认同)