Python - 如何编写更高效的 Pythonic 化简?

发布于 2024-10-25 02:50:11 字数 2194 浏览 1 评论 0原文

我正在尝试构建一个非常轻量级的 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

contains 似乎是函数式编程的教科书案例(直接从 为什么函数式编程很重要)。

问题:有没有更有效或Pythonic的方式来编写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

I'm trying to build a very lightweight Node class to serve as a Python-based hierarchy search tool. See the definition below.

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 seems to be a textbook case of functional programming (pulled directly from Why Functional Programming Matters).

Question: is there a more efficient or Pythonic way of writing contains? I know that map is usually replaced by list comprehension, but I hadn't seen a better way of doing reduce-based recursion.

Thanks,

Mike

===EDITED ... HERE'S THE REDONE CLASS TAKING INTO ACCOUNT THE ANSWER AND COMMENTS===

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

貪欢 2024-11-01 02:50:11

我认为(未经测试)您应该使用像这样的 any 而不是 reduce ,它将在第一次点击时停止:

return any(child.contains(other_node) for child in self.children)

顺便说一句,您的意思是 a.contains(b)a == blen(a.children) > 时返回 False 0?

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

a = Node("a")
b = Node("b")
a.add_child(a)
a.add_child(b)

那么

a.contains(b)

将使程序崩溃。您可能需要在 containsadd_child 中检查这一点,具体取决于您最常使用的内容。

I think (not tested) that you instead of reduce should use any like this, which will stop on the first hit:

return any(child.contains(other_node) for child in self.children)

By the way, did you mean for a.contains(b) to return False when a == b and len(a.children) > 0?

Edit: If your tree contains a loop, like this:

a = Node("a")
b = Node("b")
a.add_child(a)
a.add_child(b)

then

a.contains(b)

will crash the program. You may want to check for this either in contains or in add_child, depending on which you use the most.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文