Python 从递归生成器函数引发异常

Python 从递归生成器函数引发异常,python,generator,Python,Generator,我是Python的初学者,试图了解生成器,特别是使用yield语句。编写一些存储键和数据的经典树类 #!/usr/bin/env python3 class Tree: def __init__(self, key, data): "Create a new Tree object with empty L & R subtrees." self.key = key # store passed data self

我是Python的初学者,试图了解生成器,特别是使用yield语句。编写一些存储键和数据的经典树类

#!/usr/bin/env python3

class Tree:
    def __init__(self, key, data):
        "Create a new Tree object with empty L & R subtrees."
        self.key = key
        # store passed data
        self.data = data
        self.left = self.right = None

    def insert(self, key, data):
        "Insert a new element and data into the tree in the correct position."
        if key < self.key:
            if self.left:
                self.left.insert(key,data)
            else:
                self.left = Tree(key, data)
        elif key > self.key:
            if self.right:
                self.right.insert(key, data)
            else:
                self.right = Tree(key, data)
        else:
            raise ValueError("Attempt to insert duplicate value")

    def walk(self):
        "Generate the keys and data from the tree in sorted order."
        if self.left:
            for n in self.left.walk():
                yield n
        # change output to include data
        yield self.key,self.data
        if self.right:
            for n in self.right.walk():
                yield n
该函数可以工作-但是如果在树中找不到键,我想引发一个
keyrerror
。我试着去想它,但在使用yield语句时,我看不到一个(简单的)方法来做到这一点。具体地说,我似乎无法想出一种方法来真正知道这棵树什么时候已经完全走了,钥匙还没有找到

提前谢谢

将当前的find()重命名为_find(),然后:


我注意到
find
没有使用树已排序这一事实。这个实现如何:

def find(self, key):
    if key == self.key:
        return self.data
    if key < self.key and self.left:
        return self.left.find(key)
    if key > self.key and self.right:
        return self.right.find(key)
    raise KeyError("No such thing")
def find(self,key):
如果key==self.key:
返回self.data
如果键self.key和self.right:
返回self.right.find(键)
raise KeyError(“没有这样的事情”)

通常情况下,您不会期望返回生成器的方法在找不到任何内容时产生KeyError。KeyError适用于正在返回值或未返回值的查找。为什么不退回一台空的发电机呢?实际上,为什么它要退回一台发电机呢?键对于单个节点来说是唯一的(请参见
insert
方法),因此它可以返回数据,也可以不返回数据。是的,在仔细考虑之后,这样做可能有点愚蠢。我把这归咎于我想学习和使用发电机的意图。谢谢,在我将gen.next()改为next(gen)后,它工作得很好。我想这是在Python3?@azmo Yep中更改的-它被更改为
next(thing)
函数,以与
len(thing)
等内容保持一致-谢谢,在考虑了我的初始实现和上面David的评论之后-这似乎是一种更明智的方法。
def find(self, key):
    gen = self._find(key)
    try:
        yield gen.next()
    except StopIteration:
        raise KeyError(key)
    for item in gen:
        yield item
def find(self, key):
    if key == self.key:
        return self.data
    if key < self.key and self.left:
        return self.left.find(key)
    if key > self.key and self.right:
        return self.right.find(key)
    raise KeyError("No such thing")