如何区分迭代器和迭代? [英] How to tell the difference between an iterator and an iterable?

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

问题描述

在Python中,iterable的接口是迭代器接口的一个子集。这具有的优点是,在许多情况下,它们可以以相同的方式处理。但是,两者之间存在重要的语义差异,因为对于可迭代的 __ iter __ 返回一个新的迭代器对象而不仅仅是 self 。我怎样才能测试一个iterable真的是一个可迭代而不是一个迭代器?从概念上讲,我理解迭代是集合,而迭代器只管理迭代(即跟踪位置)但不是集合本身。

In Python the interface of an iterable is a subset of the iterator interface. This has the advantage that in many cases they can be treated in the same way. However, there is an important semantic difference between the two, since for an iterable __iter__ returns a new iterator object and not just self. How can I test that an iterable is really an iterable and not an iterator? Conceptually I understand iterables to be collections, while an iterator only manages the iteration (i.e. keeps track of the position) but is not a collection itself.

区别在于例如当一个人想要循环多次时很重要。如果给出了迭代器,那么第二个循环将不起作用,因为迭代器已经用完并直接引发 StopIteration

The difference is for example important when one wants to loop multiple times. If an iterator is given then the second loop will not work since the iterator was already used up and directly raises StopIteration.

测试 next 方法很有吸引力,但这看起来很危险,而且有些不对。我应该检查第二个循环是否为空?

It is tempting to test for a next method, but this seems dangerous and somehow wrong. Should I just check that the second loop was empty?

有没有办法以更加pythonic的方式进行这样的测试?我知道这听起来像LBYL对抗EAFP的经典案例,所以也许我应该放弃?或者我错过了什么?

Is there any way to do such a test in a more pythonic way? I know that this sound like a classic case of LBYL against EAFP, so maybe I should just give up? Or am I missing something?

编辑:
S.Lott在下面的回答中说这主要是一个缺乏问题的问题在迭代器上进行多次传递,并且首先不应该这样做。但是,在我的情况下,数据非常大,并且根据情况必须多次传递以进行数据处理(绝对没有办法解决这个问题)。

S.Lott says in his answer below that this is primarily a problem of wanting to do multiple passes over the iterator, and that one should not do this in the first place. However, in my case the data is very large and depending on the situation has to be passed over multiple times for data processing (there is absolutely no way around this).

迭代也由用户提供,并且对于单次传递足够的情况,它将与迭代器一起工作(例如,为了简单起见,由生成器创建)。但是,如果用户在需要多次传递时只提供迭代器,那么防止这种情况会很好。

The iterable is also provided by the user, and for situations where a single pass is enough it will work with an iterator (e.g. created by a generator for simplicity). But it would be nice to safeguard against the case were a user provides only an iterator when multiple passes are needed.

编辑2:
实际上这是
的一个非常好的示例抽象基础类。迭代器和迭代中的 __ iter __ 方法具有相同的名称,但是在语义上是不同的!所以 hasattr 是没用的,但 isinstance 提供了一个干净的解决方案。

Edit 2: Actually this is a very nice Example for Abstract Base Classes. The __iter__ methods in an iterator and an iterable have the same name but are sematically different! So hasattr is useless, but isinstance provides a clean solution.

推荐答案

'iterator' if obj is iter(obj) else 'iterable'

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

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