【问题标题】:BST with recursive generator带递归生成器的 BST
【发布时间】:2020-08-16 23:58:45
【问题描述】:

我有一个 Tree 类,我在其中添加了一个 in_order 递归方法(似乎运行良好)。 因为我想迭代我的 Tree 对象,所以我想我可以实现 next 下的逻辑相同,但是我得到了一个无限生成器循环。

你能告诉我我错过了什么吗?

class Tree:

    def __init__(self, left=None, right=None, data=None):
        self.data=data
        self.right=right
        self.left=left

    def in_order(self):
        if self.left is not None:
            yield from self.left.in_order()
        yield (self.data)
        if self.right is not None:
            yield from self.right.in_order()

    def __iter__(self):

        return self

    def __next__(self):
        if self.left is not None:
            yield from self.left.__next__()
        yield(self.data)
        if self.right is not None:
            yield from self.right.__next__()



t4 = Tree(data=5)
t6 = Tree(data=32)
t5 = Tree(data=10)
t1 = Tree(data=8, left=t4, right=t5)
t2 = Tree(data=35, left=t6)
t3 = Tree(left=t1, right=t2, data=20)


# Works well
gen = (t3.in_order())
for e in gen:
    print(e)

# Gets into an infinite loop
for e in t3:
    print(e)

【问题讨论】:

  • 尝试从您的代码中删除 .__next__():例如 yield from self.left
  • __next__的逻辑来看,它的内容应该移动到__iter__。你根本不需要定义__next__

标签: python recursion generator binary-search-tree yield


【解决方案1】:

评论的扩展版本:

class Tree:
    # can be simplified with @dataclass    
    def __init__(self, left=None, right=None, data=None):
        self.data=data
        self.right=right
        self.left=left

    def __iter__(self):
        if self.left is not None:
            yield from self.left
        yield (self.data)
        if self.right is not None:
            yield from self.right

     in_order = __iter__

测试:

t4 = Tree(data=5)
t6 = Tree(data=32)
t5 = Tree(data=10)
t1 = Tree(data=8, left=t4, right=t5)
t2 = Tree(data=35, left=t6)
t3 = Tree(left=t1, right=t2, data=20)
list(t3)
# returns [5, 8, 10, 20, 32, 35]

【讨论】:

  • 我认为 Iterator 需要 nextiter 实现,因为稍后运行 for 循环时,实际上是调用 next(iterator_object) 直到用尽( )。
  • @shermanv 不,这是创建迭代器的两种不同方式。如果迭代器必须是有状态的,使用__iter__ 会更容易。例如,我们从数据库中获取记录,然后实例化并生成从这些记录创建的对象。在无状态情况下(例如生成随机数),使用__next__ 更容易一一生成结果
【解决方案2】:
class Tree:

    def __init__(self, left=None, right=None, data=None):
        self.data=data
        self.right=right
        self.left=left

    def in_order(self):
        if self.left is not None:
            yield from self.left.in_order()
        yield (self.data)
        if self.right is not None:
            yield from self.right.in_order()

    def __iter__(self):
        if self.left is not None:
            yield from self.left
        yield(self.data)
        if self.right is not None:
            yield from self.right



t4 = Tree(data=5)
t6 = Tree(data=32)
t5 = Tree(data=10)
t1 = Tree(data=8, left=t4, right=t5)
t2 = Tree(data=35, left=t6)
t3 = Tree(left=t1, right=t2, data=20)


# Works well
gen = (t3.in_order())
for e in gen:
    print(e)

# Works well
for e in t3:
    print(e)

yield__next__ 一起使用时,您正在执行无限递归,如果您删除它,问题就解决了

test online

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-25
    • 2021-05-22
    • 2020-08-04
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多