检测对象是否可重复迭代 [英] Detecting that an object is repeatedly iterable

查看:236
本文介绍了检测对象是否可重复迭代的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

obj == iter(obj)暗示 obj 不能重复迭代,反之亦然?我在文档中没有看到任何这样的措辞,但根据此评论,标准库检查对象是否可重复迭代 测试如果iter(obj)是obj

Does obj == iter(obj) imply that obj isn't repeatedly iterable and vice versa? I didn't see any such wording in the docs, but according to this comment, the standard library checks if an object is repeatedly iterable by testing if iter(obj) is obj:


@agf:Python标准库的某些部分依赖于规范的这一部分; 他们通过测试<$ c来检测某些东西是否为迭代器/生成器$ c>如果iter(obj)是obj: ,因为真正的迭代器/生成器对象将 __ iter __ 定义为标识功能。如果测试为真,则转换为 list 以允许重复迭代,否则,假设对象可重复迭代,并且可以按原样使用它。

- ShadowRanger Jun 3 at 17:23

@agf: There are parts of the Python standard library that rely on this part of the spec; they detect whether something is an iterator/generator by testing if iter(obj) is obj:, because a true iterator/generator object will have __iter__ defined as the identity function. If the test is true, they convert to list to allow repeated iteration, otherwise, it's assumed that the object is repeatably iterable, and they can use it as is.
– ShadowRanger Jun 3 at 17:23

文档确实说明如果 obj 是迭代器,则需要 iter(obj)返回 OBJ 。但我认为这并不足以得出结论,可以使用 iter(obj)识别非重复可迭代对象是obj

The docs do state that if obj is an iterator, it's required that iter(obj) returns obj. But I don't think that's enough to conclude that non-repeatedly iterable objects can be identified using iter(obj) is obj.

推荐答案

所有迭代器都是迭代器,但并非所有迭代器都是迭代器。

All iterators are iterables, but not all iterables are iterators.

唯一一个可迭代的要求是它定义了一个 __ iter __()返回迭代器的方法:

The only requirement of an iterable is that it defines an __iter__() method which returns an iterator:


需要为容器对象定义一个方法以提供迭代支持:

One method needs to be defined for container objects to provide iteration support:

container .__ iter __()

返回一个迭代器对象。

container.__iter__()
Return an iterator object.

迭代器必须遵循迭代器协议,它有两个要求:

An iterator must follow the iterator protocol, which has two requirements:


  1. 它有一个 __ iter __()方法返回对象本身


iterator .__ iter __()

返回迭代器对象本身。

iterator.__iter__()
Return the iterator object itself.


  • 它有一个 __ next __()方法在每次调用时返回下一个项目,并且一旦用完,就会引发 StopIteration

  • It has a __next__() method which returns the next item on each call, and, once exhausted, raises StopIteration on every subsequent call:


    一旦迭代器的 __ next __()方法引发 StopIteration ,它必须在后续调用中继续这样做。不遵守此属性的实现被视为已损坏。

    Once an iterator’s __next__() method raises StopIteration, it must continue to do so on subsequent calls. Implementations that do not obey this property are deemed broken.


  • 这些要求意味着迭代器永远不会重复,并且您可以通过确认 iter(obj)是obj <$ c来确认iterable是迭代器(因此根据定义不可重复) $ c> True :

    These requirements mean that iterators are never repeatable, and that you can always confirm that an iterable is an iterator (and therefore unrepeatable by definition) by confirming that iter(obj) is obj is True:

    def is_unrepeatable(obj):
        return iter(obj) is obj
    

    但是:因为可迭代的唯一要求是 iter(obj)返回某些迭代器,无法证明 重复。一个iterable可以定义一个 __ iter __()方法,它在每次调用时返回一个具有不同行为的迭代器:例如,它可以返回一个迭代器,它在第一次迭代它的元素它被调用,但在后续调用中,返回一个迭代器,它立即引发 StopIteration

    However: since the only requirement of an iterable is that iter(obj) returns some iterator, you can't prove that it is repeatable. An iterable could define an __iter__() method which returns an iterator with different behaviour each time it's called: for instance, it could return an iterator which iterates over its elements the first time it's called, but on subsequent calls, return an iterator which immediately raises StopIteration.

    这种行为很奇怪(并且很烦人,但不是禁止的。下面是一个不可重复的可迭代类的示例,它不是迭代器:

    This behaviour would be strange (and annoying), but is not prohibited. Here's an example of a non-repeatable iterable class which is not an iterator:

    class Unrepeatable:
    
        def __init__(self, iterable):
            self.iterable = iterable
            self.exhausted = False
    
        def __iter__(self):
            if self.exhausted:
                return
            else:
                self.exhausted = True
                yield from self.iterable
    

    >>> x = Unrepeatable([1,2,3])
    >>> list(x)
    [1, 2, 3]
    >>> list(x)
    []
    >>> iter(x) is x
    False
    >>> 
    

    我会毫不犹豫地称这样的虚假迭代器表现得很糟糕,我可以'想到你在野外找到一个的情况,但如上所示,它是可能的。

    I wouldn't hesitate to call such a "fake iterator" badly-behaved, and I can't think of a situation where you'd find one in the wild, but as demonstrated above, it is possible.

    这篇关于检测对象是否可重复迭代的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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