可以在此用例中使用Python列表理解吗?

时间:2019-05-15 18:22:32

标签: python list-comprehension

最近,我不得不遍历一棵树,从任意节点开始直到它的根。我写了一些类似的东西

breadcrumbs = []
while node is not None:
    breadcrumbs.append(node.get_text())
    node = node.get_parent()

在我看来,它看起来很像使用列表构造的丑陋实现

result = []
while node is not None:
    result.append(node.get_text())
    node = node.next()

而不是更惯用的列表理解

result = [node.get_text() for node in nodes]

这让我想知道是否有一种更惯用的从树遍历构造列表的方法。为了完整起见(并且由于上面的摘录主要是伪代码),这是我使用的实际代码:

model, treeiter = self.treeview.get_selection().get_selected()
breadcrumbs = []
while treeiter is not None:
    breadcrumbs.append(model.get_value(treeiter, self.COL_TEXT))
    treeiter = model.iter_parent(treeiter)
path = '/'.join(reversed(breadcrumbs))

对于上下文,第一行调用Gtk.TreeSelection.get_selected(其返回值之一在API中称为iter,但与Python迭代器无关)。我的代码从用户选择的路径(例如,在下面的示例中为"A/b/2")创建一个字符串:

+- A
|  |- a
|  \- b
|     |- 1
|     \- 2       <- selected element
\- B
   |- c
   \- d

2 个答案:

答案 0 :(得分:3)

是的,您使用的树结构不是非常pythonic。但是,您可以使用自制的generators轻松地将其转换为更具Python风格的解决方案。

例如,要遍历父母(或祖先),您可以定义一个iter_parents函数,如下所示:

def iter_parents(node):
    while node is not None:
        yield node
        node = node.get_parent()

有了这个,您可以像这样构建面包屑:

breadcrumbs = [node.get_text() for node in iter_parents(branch)]

这是一个小演示:

class Node(object):
    def __init__(self, text, parent=None):
        self._text = text
        self._parent = parent

    def get_text(self):
        return self._text

    def get_parent(self):
        return self._parent


branch = Node("c", Node("b", Node("a")))

breadcrumbs = [node.get_text() for node in iter_parents(branch)]

print(breadcrumbs)
# -> ['c', 'b', 'a']

对于node.next(),您可以以相同的方式定义iter_next()生成器。

修改

使用reverse来反转列表,例如:

breadcrumbs = [node.get_text() for node in iter_parents(branch)]
breadcrumbs.reverse()

print(breadcrumbs)
# -> ['a', 'b', 'c']

答案 1 :(得分:0)

当然,您可以将while循环包装在这样的生成器中:

def get_parents(node):
    while node is not None:
        yield node
        node.get_parent()

然后您可以使用:

result = [node.get_text() for node in get_parents(nodes)]