Python 为什么可以';我的块是否捕获StopIteration异常?
我想用这个程序做的是,我想让它通过递归一次又一次地返回“是”和“否”。请帮忙!我做错什么了吗Python 为什么可以';我的块是否捕获StopIteration异常?,python,Python,我想用这个程序做的是,我想让它通过递归一次又一次地返回“是”和“否”。请帮忙!我做错什么了吗 def yes_or_no(): for x in ("yes","no"): try: yield x except (StopIteration): return yes_or_no() gen = yes_or_no() print(next(gen)) print(next(gen)) print(next(gen)) 当它到达第三次打印时,
def yes_or_no():
for x in ("yes","no"):
try:
yield x
except (StopIteration):
return yes_or_no()
gen = yes_or_no()
print(next(gen))
print(next(gen))
print(next(gen))
当它到达第三次打印时,它会显示StopIteration,即使我认为我在错误处理中捕获了它?在
yield
调用中不会引发StopIteration
异常,因此您不会通过try/except设置捕获它
通过在函数中使用yield
语句,您已经将其转换为生成器(您似乎理解)。每次评估生成器时,它将在上次完成的产量处重新输入,并继续执行,直到下一个产量或函数完成。因此,在第三次next()
,执行将在产生时恢复,返回for
循环,查看它是否完成,然后继续执行,在本例中,这只是函数的结束。函数将返回,因此生成器将提高其StopIteration
我不建议在这个任务中使用递归;只需在(“是”、“否”)循环周围使用一个外部无限循环(或者更好的是,使用itertools中的某些内容)
如果您真的想使用递归,那么您可能想试试
def yes_或_no():
对于x英寸(“是”、“否”):
产量x
是或否的收益率()
我认为yield from
位需要Python>=3.3。在yield
调用中没有引发StopIteration
异常,因此您将无法通过try/except设置捕获它
通过在函数中使用yield
语句,您已将其转换为生成器(您似乎理解)。每次对生成器求值时,它都将在上次完成的yield处重新输入,并一直执行到下一个yield或函数完成。因此,在第三个next()
,执行将在yield
处恢复,返回for
循环,查看它是否完成,然后继续执行,在这种情况下,这只是函数的结束。函数将返回,因此生成器将提升其StopIteration
我不建议您在这个任务中使用递归;只需在(“yes”,“no”)循环周围使用一个外部无限循环(或者更好的是,使用itertools中的某些东西)
如果您真的想使用递归,那么您可能想试试
def yes_或_no():
对于x英寸(“是”、“否”):
产量x
是或否的收益率()
我认为,yield from
位需要Python>=3.3。循环中的yield x
永远不会引发StopIteration
,因此您无法捕获它。Pythonfor
循环是使用StopIteration
实现的,这是真的,但是在您处理它之前就捕获了在那里引发的实例
让你的想法发挥作用的方法就是。。。让循环运行,然后生成其余的元素。递归地:
def yes_or_no():
for x in ("yes","no"):
yield x
yield from yes_or_no()
另一方面:yield from
是继续生成递归调用生成的元素所需要的。生成器的返回值
无助于生成更多元素。具有讽刺意味的是,事实上,它设置了一个异常,该异常导致生成器在元素不足的情况下运行:
>>> def example():
... yield 1
... return 2
...
>>> x = example()
>>> next(x)
1
>>> next(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration: 2
或者使用itertools
:
>>> import itertools
>>> x = itertools.cycle(('yes', 'no'))
>>> next(x)
'yes'
>>> next(x)
'no'
>>> next(x)
'yes'
>>> next(x)
'no'
那么,如何在用户代码中充分利用StopIteration
?或者在迭代器实现中显式地提升它(尽管最明显的方法已经为您完成了),或者在您使用next
手动提升迭代器时捕捉它。示例:
class SingletonIterator:
"""Proxy iterator to allow 'iteration' over a fictitious sequence
holding a single element, the `value`."""
def __init__(self, value):
self._value = value
self._yielded = False
def __iter__(self):
return self
def __next__(self):
if self._yielded:
raise StopIteration
self._yielded = True
return self._value
def first(predicate, sequence):
"""The first element `e` of `sequence` satisfying `predicate(e)`.
Raises ValueError for an empty sequence."""
try:
return next(e for e in sequence if predicate(e))
except StopIteration:
raise ValueError('empty sequence')
yield x
循环内部永远不会引发StopIteration
,因此您无法捕获它。Pythonfor
循环是使用StopIteration
实现的,这是真的,但是在您处理它之前就捕获了在那里引发的实例
让你的想法发挥作用的方法就是。。。让循环运行,然后生成其余的元素。递归地:
def yes_or_no():
for x in ("yes","no"):
yield x
yield from yes_or_no()
另一方面:yield from
是继续生成递归调用生成的元素所需要的。生成器的返回值
无助于生成更多元素。具有讽刺意味的是,事实上,它设置了一个异常,该异常导致生成器在元素不足的情况下运行:
>>> def example():
... yield 1
... return 2
...
>>> x = example()
>>> next(x)
1
>>> next(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration: 2
或者使用itertools
:
>>> import itertools
>>> x = itertools.cycle(('yes', 'no'))
>>> next(x)
'yes'
>>> next(x)
'no'
>>> next(x)
'yes'
>>> next(x)
'no'
那么,如何在用户代码中充分利用StopIteration
?或者在迭代器实现中显式地提升它(尽管最明显的方法已经为您完成了),或者在您使用next
手动提升迭代器时捕捉它。示例:
class SingletonIterator:
"""Proxy iterator to allow 'iteration' over a fictitious sequence
holding a single element, the `value`."""
def __init__(self, value):
self._value = value
self._yielded = False
def __iter__(self):
return self
def __next__(self):
if self._yielded:
raise StopIteration
self._yielded = True
return self._value
def first(predicate, sequence):
"""The first element `e` of `sequence` satisfying `predicate(e)`.
Raises ValueError for an empty sequence."""
try:
return next(e for e in sequence if predicate(e))
except StopIteration:
raise ValueError('empty sequence')
下面是一个简单的递归解决方案:
def yes_or_no():
yield from ('yes', 'no')
yield from yes_or_no()
编辑:
itertools
模块具有接收迭代器并返回循环输入的生成器的功能
import itertools
def yes_or_no():
yield from itertools.cycle(("yes", "no"))
下面是一个简单的递归解决方案:
def yes_or_no():
yield from ('yes', 'no')
yield from yes_or_no()
编辑:
itertools
模块具有接收迭代器并返回循环输入的生成器的功能
import itertools
def yes_or_no():
yield from itertools.cycle(("yes", "no"))
这将不起作用,因为for循环只运行两次。您是否正在尝试创建一个循环函数,如?当两次迭代后for
循环结束时,该函数将返回(在退出时不会引发StopIteration
异常)。这将不起作用,因为for循环只会运行两次。您是否正在尝试创建一个循环函数,如?当两次迭代后for
循环结束时,函数将返回(在退出时不会引发StopIteration
异常)。您对版本要求的看法是正确的:您对版本要求的看法是正确的: