关于exausted迭代器的问题 [英] Question about exausted iterators

查看:96
本文介绍了关于exausted迭代器的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当你试图从一个已经exausted迭代器中获取一个元素时,有没有一个很好的理由,它抛出StopIteration而不是其他一些

异常?我已经失去了很多次因为我使用了很多

的迭代器而且我忘了那个特定的函数参数是一个。


例如:

Is there a good reason why when you try to take an element from an
already exausted iterator, it throws StopIteration instead of some other
exception ? I''ve lost quite some times already because I was using a lot
of iterators and I forgot that that specific function parameter was one.

Exemple :

def f(i):
.... print list(i)

....打印清单(i)

.... f(iter(范围(2)))
[0,1]

[]
def f(i): .... print list(i)
.... print list(i)
.... f(iter(range(2))) [0, 1]
[]




这是使用Python 2.4.2



This is using Python 2.4.2

推荐答案



" Christophe" < CH ************* @ free.fr>在消息中写道

news:44 ********************** @ news.free.fr ...

"Christophe" <ch*************@free.fr> wrote in message
news:44**********************@news.free.fr...
有没有一个很好的理由当你试图从一个
已经exausted迭代器中取一个元素时,它会抛出StopIteration而不是其他一些
异常?


是。

..

..

区分控制信息I我按照

代码规范完成了产生价值(所以不要再打扰我了)。来自错误信息

说有些事情是错的,我不能屈服于价值而放弃。在其他

字中,区分预期的正确行为与意外的错误

行为。这对于迭代器的正常和正确使用至关重要。

我已经丢失了很多次因为我使用了大量的迭代器而我忘了那个特定的函数参数是一。


我认为你的意思是''特定函数参数''参数可以是任何可迭代的参数。

例如:
Is there a good reason why when you try to take an element from an
already exausted iterator, it throws StopIteration instead of some other
exception ?
Yes.
..
..
To distinguish the control message "I am done yielding values, as per the
code specification (so don''t bother calling me again)." from error messages
that say "Something is wrong, I cannot yield values and give up." In other
words, to distinguish expected correct behavior from unexpected incorrect
behavior. This is essential for the normal and correct use of iterators.
I''ve lost quite some times already because I was using a lot
of iterators and I forgot that that specific function parameter was one.
I think you mean ''specific function argument'' for a parameter which could
be any iterable.
Exemple :



示例


Example

def f(i):...打印列表(i)
...打印列表(i)
... f(iter(范围(2)))
def f(i): ... print list(i)
... print list(i)
... f(iter(range(2)))


[0,1 ]
[]


[0, 1]
[]




按照规范。

我猜你想让第一个list()调用正常终止并且

返回一个列表,这需要用尽我提升StopIteration,而你

想要第二个list()不终止但是引发异常,这个

需要用尽i来提高StopIteration以外的东西。很难。


一个解决方案是通话清单(i)一次:


def f(i):

li = list(i)

print li

print li


另一种是将f记录为要求我是一个非迭代器可重复

可迭代并且只传递正确的参数。


三分之一是添加一行如

if iter( i)是i:引发TypeError(输入似乎是迭代器)


这不太准确,因为它会不正确地排除自我迭代器

重复(我相信,没有内置)和不正确地传递

不可重复的非迭代器迭代(至少一些文件对象)。但它

可能适用于所有情况。


Terry Jan Reedy



As per specification.
I am guessing that you want the first list() call to terminate normally and
return a list, which requires exhausted i to raise StopIteration, while you
want the second list() to not terminate but raise an exception, which
requires exhausted i to raise something other than StopIteration. Tough.

One solution is call list(i) exactly once:

def f(i):
li = list(i)
print li
print li

Another is to document f as requiring that i be a non-iterator reiterable
iterable and only pass correct arguments.

A third is to add a line like
if iter(i) is i: raise TypeError("input appears to be iterator")

This is not quite exact since it will improperly exclude self-iterator
reiterables (which, I believe, no builtin is) and improperly pass
non-reiterable non-iterator iterables (at least some file objects). But it
might work for all your cases.

Terry Jan Reedy


Christophe写道:
Christophe wrote:
当你试图从一个
已经exausted迭代器中获取一个元素时,它有一个很好的理由,它抛出StopIteration而不是其他一些
例外?我已经失去了很多次因为我使用了很多迭代器,我忘了那个特定的函数参数是一个。

例如:
Is there a good reason why when you try to take an element from an
already exausted iterator, it throws StopIteration instead of some other
exception ? I''ve lost quite some times already because I was using a lot
of iterators and I forgot that that specific function parameter was one.

Exemple :
>>> def f(i):...打印列表(i)
...打印列表(i)
...>>> f(iter(range(2)))
>>> def f(i): ... print list(i)
... print list(i)
... >>> f(iter(range(2)))


[0,1]
[]


[0, 1]
[]




是否尝试迭代耗尽的迭代器应该被处理

不同的是依赖于appication。在大多数情况下,你并不是真的想要区分一个不产生元素的迭代器和一个之前产生了一些元素但它已经用尽的一个元素的b $ b迭代器。 。

如果你关心,你可以滚动你自己的迭代器包装器:

class ExhaustibleIterator(object):

def __init __(self,iterable ):

self._next = getattr(可迭代,''下一个'',iter(可迭代).next)

self._exhausted = False


def next(self):

if self._exhausted:

raise ExhaustedIteratorException()

try:return self。 _next()

除了StopIteration:

self._exhausted = True

raise


def __iter__ (个体经营):

返回自我

类ExhaustedIteratorException(例外):

pass

And然后在你的功能:

def f(i):

i = ExhaustibleIterator(i)

打印列表(i)

打印列表(i)

HTH,

George



Whether trying to iterate over an exhausted iterator should be treated
differently is appication dependent. In most cases, you don''t really
care to distinguish between an iterator that yields no elements and an
iterator that did yield some elements before but it has been exhausted.
If you do care, you can roll your own iterator wrapper:
class ExhaustibleIterator(object):
def __init__(self, iterable):
self._next = getattr(iterable, ''next'', iter(iterable).next)
self._exhausted = False

def next(self):
if self._exhausted:
raise ExhaustedIteratorException()
try: return self._next()
except StopIteration:
self._exhausted = True
raise

def __iter__(self):
return self

class ExhaustedIteratorException(Exception):
pass
And then in your function:
def f(i):
i = ExhaustibleIterator(i)
print list(i)
print list(i)
HTH,
George


Terry Reedyaécrit:
Terry Reedy a écrit :
" Christophe" < CH ************* @ free.fr>在消息中写道
新闻:44 ********************** @ news.free.fr ......
"Christophe" <ch*************@free.fr> wrote in message
news:44**********************@news.free.fr...
有一个很好的理由当你试图从一个
已经exausted迭代器中获取一个元素时,它会抛出StopIteration而不是其他一些
异常吗?

是的。


要区分控制信息我已经完成了产生价值,按照
代码规范(所以不要再打电话给我了)。来自错误信息
说有些事情是错的,我不能屈服于价值而放弃。用其他词语来区分预期的正确行为和意外的错误行为。这对正常和正确使用迭代器至关重要。
Is there a good reason why when you try to take an element from an
already exausted iterator, it throws StopIteration instead of some other
exception ?

Yes.
.
.
To distinguish the control message "I am done yielding values, as per the
code specification (so don''t bother calling me again)." from error messages
that say "Something is wrong, I cannot yield values and give up." In other
words, to distinguish expected correct behavior from unexpected incorrect
behavior. This is essential for the normal and correct use of iterators.




你谈到预期的行为,我的预期行为是

迭代器应该一旦它引发StopIteration一次就无法使用。



You talk about expected behaviour and my expected behaviour is that an
iterator should not be usable once it has raised StopIteration once.

> def f(i):
>def f(i):



...打印清单(i)
...打印清单(i)
...



... print list(i)
... print list(i)
...

> f (iter(范围(2)))
>f(iter(range(2)))



[0,1]
[]



[0, 1]
[]



按照规范。


As per specification.




规格有时会出现错误我也猜测你希望第一个list()调用正常终止并且
返回一个列表,这需要用尽我提升StopIteration,而你想要第二个list()不终止但引发异常,这需要用尽我提出的东西而不是StopIteration。强硬。


完全正确。这将是一个理智的方式来处理它。

一个解决方案是呼叫列表(i)恰好一次:

def f(i):
li = list (i)打印li
打印li



Specifications sometimes have "bugs" too.
I am guessing that you want the first list() call to terminate normally and
return a list, which requires exhausted i to raise StopIteration, while you
want the second list() to not terminate but raise an exception, which
requires exhausted i to raise something other than StopIteration. Tough.
Exactly. This would be a sane way to handle it.
One solution is call list(i) exactly once:

def f(i):
li = list(i)
print li
print li




好​​的,如果你愿意,可以叫我傻,但我完全清楚解决方案

到那个问题!来吧,我正在使用迭代器显示一个可怕的示例代码

gotcha。


而不是说所有工作都按预期工作你可能会有点

有用并告诉我为什么它的意图明显是破碎的

而不是?



Ok, call me stupid if you want but I know perfectly well the "solution"
to that problem ! Come on, I was showing example code of an horrible
gotcha on using iterators.

Instead of saying that all works as intended could you be a little
helpful and tell me why it was intended in such an obviously broken way
instead ?


这篇关于关于exausted迭代器的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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