【问题标题】:Type error 'Type' not iterable error when using generator使用生成器时类型错误“类型”不可迭代错误
【发布时间】:2016-03-10 18:20:32
【问题描述】:

我添加了一个生成器函数,以便能够迭代预定义的 BinaryTree 类,但是当我使用测试代码运行它时,我收到一个 TypeError 说 BinaryTree 类不可迭代,我不知道为什么。以下是提供的代码以及用于遍历树的生成器函数以及测试代码:

# Implement generator function to make class iterable

class BinaryTree:
    def __init__(self, content, leftSubtree=None, rightSubtree=None):
        self.content = content
        self.leftSubtree = leftSubtree
        self.rightSubtree = rightSubtree

    def __repr__(self):
        return str(self.content)

    def traverse(self):  # Generator implementation
        if self.rightSubtree:
            for leaf in self.rightSubtree:
                yield leaf
        yield self.content
        if self.leftSubtree:
            for leaf in self.leftSubtree:
                yield leaf

# Testing code

Node = BinaryTree

if __name__ == '__main__':
    s = Node(1) # Binary tree with 1 Node
    t = Node(10, s, None)   # Binary tree with 10 as content, 1 as left subtree
    tree = BinaryTree(20, None, t)  # Binary tree with 20 as content, no left subtree and t as right subtree

for x in (s, t, tree):
    print(x)

for node in tree:
    print(node)

这是之后打印出来的错误:

1
Traceback (most recent call last):
10
20
  File "...binaryTree_adt.py", line 34, in <module>
for node in tree:
TypeError: 'BinaryTree' object is not iterable

Process finished with exit code 1

我知道对于生成器,您不需要创建迭代器类,因为生成器将以类似的方式遍历项目。当我将“traverse”方法的名称更改为 iter 时,我没有收到任何错误,但是当名称更改时,我会这样做。

【问题讨论】:

    标签: python iterator generator


    【解决方案1】:

    BinaryTree 本身不可迭代,不。只有BinaryTree().traverse()方法产生的结果是:

    for node in tree.traverse():
    

    但是,您还需要调整方法本身以使用子节点的.traverse() 方法:

    def traverse(self):  # Generator implementation
        if self.rightSubtree:
            for leaf in self.rightSubtree.traverse():
                yield leaf
        yield self.content
        if self.leftSubtree:
            for leaf in self.leftSubtree.traverse():
                yield leaf
    

    如果你想让一个实例 itself 可迭代,你需要实现一个__iter__ method,它要么返回一个迭代器(例如,生成器函数产生这个),要么返回__self__点您还需要提供next 或__next__ 方法,具体取决于您的Python 版本。

    在这里,将 traverse 重命名为 __iter__ 就足够了:

    class BinaryTree:
        def __init__(self, content, leftSubtree=None, rightSubtree=None):
            self.content = content
            self.leftSubtree = leftSubtree
            self.rightSubtree = rightSubtree
    
        def __repr__(self):
            return str(self.content)
    
        def __iter__(self):
            if self.rightSubtree:
                for leaf in self.rightSubtree:
                    yield leaf
            yield self.content
            if self.leftSubtree:
                for leaf in self.leftSubtree:
                    yield leaf
    

    演示:

    >>> class BinaryTree:
    ...     def __init__(self, content, leftSubtree=None, rightSubtree=None):
    ...         self.content = content
    ...         self.leftSubtree = leftSubtree
    ...         self.rightSubtree = rightSubtree
    ...     def __repr__(self):
    ...         return str(self.content)
    ...     def __iter__(self):
    ...         if self.rightSubtree:
    ...             for leaf in self.rightSubtree:
    ...                 yield leaf
    ...         yield self.content
    ...         if self.leftSubtree:
    ...             for leaf in self.leftSubtree:
    ...                 yield leaf
    ...
    >>> Node = BinaryTree
    >>> s = Node(1)
    >>> t = Node(10, s, None)
    >>> tree = BinaryTree(20, None, t)
    >>> for x in (s, t, tree):
    ...     print(x)
    ...
    1
    10
    20
    >>> for node in tree:
    ...     print(node)
    ...
    10
    1
    20
    

    【讨论】:

    • 当我最初使用名称 iter 时,代码产生了正确的输出。我只是很困惑为什么即使使用了生成器(yield)也需要这样命名?
    • @BrxttB:生成器是一种生成可迭代对象的方法;调用traversable() 的结果是可迭代的。您可以在不使用 yield 的情况下使实例可迭代;只需从__iter__ 返回self 并让__next__ 在每次调用时产生一个值。
    • @BrxttB:请参阅 How to make class iterable? 以获取无需使用 yield 即可迭代的类的示例。
    • 我知道如何使用 iter 使其可迭代,只是在这种特殊情况下我需要使用生成器,所以我的印象是使用生成器你不需要'不需要定义 iter 方法。只是使用“yield”的方法
    猜你喜欢
    • 2022-11-30
    • 2021-02-13
    • 1970-01-01
    • 2022-11-29
    • 2021-10-28
    • 2012-10-30
    • 2017-03-05
    • 1970-01-01
    • 2021-07-28
    相关资源
    最近更新 更多