Python - 如何编写更高效、Pythonic 的 reduce?
我正在尝试构建一个非常轻量级的节点类,用来作为一个基于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
contains
这个函数看起来是功能编程的经典案例(直接取自 为什么功能编程很重要)。
问题是:有没有更高效或者更符合Python风格的写法来实现 contains
?我知道 map
通常可以用列表推导式来替代,但我还没见过更好的方法来处理基于 reduce
的递归。
谢谢,
迈克
===已编辑... 这是根据回答和评论重新做的类===
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
1 个回答
5
我觉得(虽然没测试过)你应该用 any
来代替 reduce
,这样可以在找到第一个符合条件的情况下就停止:
return any(child.contains(other_node) for child in self.children)
顺便问一下,你是想让 a.contains(b)
在 a == b
并且 len(a.children) > 0
的时候返回 False
吗?
编辑:如果你的树结构里有个循环,比如这样:
a = Node("a")
b = Node("b")
a.add_child(a)
a.add_child(b)
那么
a.contains(b)
程序就会崩溃。你可能需要在 contains
或者 add_child
中检查这个问题,具体看你哪个用得更多。