实现__iter__的对象为什么不能被识别为可迭代的? [英] How come an object that implements __iter__ is not recognized as iterable?

查看:80
本文介绍了实现__iter__的对象为什么不能被识别为可迭代的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设您使用包装对象:

class IterOrNotIter:
    def __init__(self):
        self.f = open('/tmp/toto.txt')
    def __getattr__(self, item):
        try:
            return self.__getattribute__(item)
        except AttributeError:
            return self.f.__getattribute__(item)

此对象实现__iter__,因为它将对它的任何调用传递给实现它的成员f.恰当的例子:

This object implements __iter__, because it passes any call to it to its member f, which implements it. Case in point:

>>> x = IterOrNotIter()
>>> x.__iter__().__next__()
'Whatever was in /tmp/toto.txt\n'

根据文档( https://docs.python.org /3/library/stdtypes.html#iterator-types ),因此IterOrNotIter应该是可迭代的.

According to the documentation (https://docs.python.org/3/library/stdtypes.html#iterator-types), IterOrNotIter should thus be iterable.

但是,Python解释器无法将IterOrNotIter对象识别为实际上是可迭代的:

However, the Python interpreter does not recognize an IterOrNotIter object as actually being iterable:

>>> x = IterOrNotIter()
>>> for l in x:
...    print(l)
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'IterOrNotIter' object is not iterable

这可行:

>>> x = IterOrNotIter()
>>> for l in x.f:
...    print(l)
...
Whatever was in /tmp/toto.txt

我不明白为什么.

推荐答案

基本上是因为您的类没有真正的__iter__方法:

Basically because your class just doesn't have a real __iter__ method:

>>> hasattr(IterOrNotIter, '__iter__')
False

因此它没有资格作为迭代器,因为对__iter__的实际检查将检查是否存在,而不是假设已实现.因此,(不幸的是)使用__getattr____getattribute__的变通办法不起作用.

So it doesn't qualify as iterator because the actual check for __iter__ checks for the existence instead of assuming it's implemented. So workarounds with __getattr__ or __getattribute__ (unfortunatly) don't work.

__getattribute__ 的文档中实际上提到了这一点. :

This is actually mentioned in the documentation for __getattribute__:

注意

由于通过语言语法或内置函数进行隐式调用而查找特殊方法时,仍可能会绕过此方法.请参见特殊方法查找.

后一部分还说明了为什么:

以这种方式绕过__getattribute__()机器为解释器内的速度优化提供了很大的空间,但以牺牲一些特殊方法的灵活性为代价(特殊方法必须在类对象本身中设置以便被解释程序一致地调用).

Bypassing the __getattribute__() machinery in this fashion provides significant scope for speed optimisations within the interpreter, at the cost of some flexibility in the handling of special methods (the special method must be set on the class object itself in order to be consistently invoked by the interpreter).

强调我的.

这篇关于实现__iter__的对象为什么不能被识别为可迭代的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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