生成器表达式的if子句中的StopIteration [英] StopIteration in the if clause of a generator expression

查看:73
本文介绍了生成器表达式的if子句中的StopIteration的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了混淆新手和老手,Bengt Richter写道:

需要更直接的东西,例如,包裹的单行:

>>> def guess(n = 3):print(你是对的!,不再尝试
>>>你!!!'')[n-1 in。 ..(x为x in xrange(n)for t in [raw_input(''猜我的名字:
'')==''本'']
...如果不是或者是([])。next())]
...>>> guess()


为了使它更清晰一点,在生成器表达式中引发一个StopIteration

默默地终止该生成器:

def stop():提高StopIteration
.... list(如果i< 5或者stop()),i在范围(10)中为i
[0,1,2,3,4]


另一方面,在列表理解中,它被传播:

[i for i in range(10)if i< 5或stop()]



回溯(最近一次调用最后一次):

文件"< stdin>" ;,第1行,在?

文件"< stdin>",第1行,在停止

StopIteration


这是故意的差异吗?


彼得

解决方案

Peter Otten写道:< blockquote class =post_quotes>为了让一个新手和老手混淆,Bengt Richter写道:


让我换了一个:)


为了使它更清晰一点,在生成器表达式中引发的StopIteration静默地终止该生成器:




*任何*从生成器引发的异常,终止发电机

jfj


Peter Otten写道:

为了让新手和老手混淆,Bengt Richter写道:

需要更直接的东西,例如,包裹的单行:

>>> def guess(n = 3):print(你是对的!,不再尝试
>>>你!!!'')[n-1 in。 ..(x为x in xrange(n)for t in [raw_input(''猜我的名字:
'')==''本'']
...如果不是或者是([])。next())]
...

>>>猜测()
为了使它更清晰一点,在生成器中引发的StopIteration



表达式默默地终止该生成器:
def stop():引发StopIteration。 ..列表(我在范围(10)中的i,如果我<5或停止())[0,1,2,3,4]

在列表理解中,另一方面,它被传播:
[i for i in range(10)if i< 5或stop()]


Traceback(最近一次调用最后一次):
文件"< stdin>",第1行,在?
文件中"< stdin>",第1行,停止
StopIteration

这是故意的差异吗?



非常有趣。我不确定设计师是否甚至认为这个特别微妙。为什么会发生这种情况很简单。在生成器

表达式的情况下,生成器表达式确实传播了

StopIteration,但是list()将其捕获。列表推导在内部

被视为for-loop(种类),它没有陷入StopIteration。

也许它应该。

列表理解[x for y in y]目前被视为

等效于以下内容,具有字节码优化:


.. _ = []

..对于x中的x:

.. _.append(x)

也许它应该是相当于:


.. _ = []

..试试:

.. for x in y:

.. _.append(x)

..除了StopIteration:

..传递

然而,我会猜猜蟒蛇神不会赞成这种使用

StopIteration,所以不会为此付出任何牺牲。

尽管如此,它似乎也是如此列表理解会在Python 3.0中表现出来,所以也许我们应该这样做。

-

CARL BANKS


[Peter Otten]

在生成器表达式中引发的StopIteration静默终止该生成器:

def stop():引发StopIteration。 ..列表(如果i
另一方面,在列表理解中,它被传播:
[i for i in range( 10)如果我< 5或stop()]


Traceback(最近一次调用最后一次):
文件"< stdin>",第1行,在?
文件中"< stdin>",第1行,停止
StopIteration

这是故意的差异吗?




我会把它称为不幸的不对称 - 一个永远不会出现的,除非

你没有好处;-)


在某种程度上,两者都是表现相同。他们都提出了StopIteration。在生成器表达式的

的情况下,封闭的

list()调用拦截了StopIteration。如果你为

列表写一个纯python等价物就很明显了:


def lyst(s):

it = iter (s)

结果= []

尝试:

而1:

result.append(它。下一个())

除了StopIteration:#猜猜谁被困StopIter

返回结果

Raymond Hettinger


To confuse a newbies and old hands alike, Bengt Richter wrote:

Need something more straightforward, e.g., a wrapped one-liner:

>>> def guess(n=3): print ("You''re right!", ''No more tries for
>>> you!!!'')[n-1 in ... (x for x in xrange(n) for t in [raw_input(''Guess my name:
'')==''Ben'']
... if not t or iter([]).next())]
... >>> guess()
To make it a bit clearer, a StopIteration raised in a generator expression
silently terminates that generator:
def stop(): raise StopIteration .... list(i for i in range(10) if i < 5 or stop()) [0, 1, 2, 3, 4]

In a list comprehension, on the other hand, it is propagated:
[i for i in range(10) if i < 5 or stop()]


Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 1, in stop
StopIteration

Is that an intentional difference?

Peter

解决方案

Peter Otten wrote:

To confuse a newbies and old hands alike, Bengt Richter wrote:
got me for one:)


To make it a bit clearer, a StopIteration raised in a generator expression
silently terminates that generator:



*any* exception raised from a generator, terminates the generator
jfj


Peter Otten wrote:

To confuse a newbies and old hands alike, Bengt Richter wrote:

Need something more straightforward, e.g., a wrapped one-liner:

>>> def guess(n=3): print ("You''re right!", ''No more tries for
>>> you!!!'')[n-1 in ... (x for x in xrange(n) for t in [raw_input(''Guess my name:
'')==''Ben'']
... if not t or iter([]).next())]
...

>>> guess()
To make it a bit clearer, a StopIteration raised in a generator


expression silently terminates that generator:
def stop(): raise StopIteration ... list(i for i in range(10) if i < 5 or stop()) [0, 1, 2, 3, 4]

In a list comprehension, on the other hand, it is propagated:
[i for i in range(10) if i < 5 or stop()]


Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 1, in stop
StopIteration

Is that an intentional difference?


Very interesting. I''m not sure if the designers even considered this
particular subtlety. Why it happens is pretty plain. In the generator
expression case, the generator expression does propogate the
StopIteration, but list() traps it. List comprehensions are internally
treated as a for-loop (kind of), which doesn''t trap StopIteration.
Maybe it should.

The list comprehension [ x for x in y ] is currently treated as
equivalent to the following, with byte-code optimizations:

.. _ = []
.. for x in y:
.. _.append(x)
Perhaps it ought to be equivalent to:

.. _ = []
.. try:
.. for x in y:
.. _.append(x)
.. except StopIteration:
.. pass
However, I would guess the Python gods wouldn''t approve of this use of
StopIteration, and so would make no sacrifices to get it.
Nevertheless, it seems likely to be how a list comprehension would
behave in Python 3.0, so maybe we should do it.
--
CARL BANKS


[Peter Otten]

a StopIteration raised in a generator expression
silently terminates that generator:

def stop(): raise StopIteration ... list(i for i in range(10) if i < 5 or stop()) [0, 1, 2, 3, 4]

In a list comprehension, on the other hand, it is propagated:
[i for i in range(10) if i < 5 or stop()]


Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 1, in stop
StopIteration

Is that an intentional difference?



I would call it an unfortunate assymmetry -- one the never comes up unless
you''re up to no good ;-)

In a way, both behave identically. They both raise StopIteration. In the case
of the generator expression, that StopIteration is intercepted by the enclosing
list() call. That becomes obvious if you write a pure python equivalent for
list:

def lyst(s):
it = iter(s)
result = []
try:
while 1:
result.append(it.next())
except StopIteration: # guess who trapped StopIter
return result
Raymond Hettinger


这篇关于生成器表达式的if子句中的StopIteration的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆