Python 为什么实现了iter的对象不能被识别为iterable?
假设您使用包装器对象:Python 为什么实现了iter的对象不能被识别为iterable?,python,python-3.x,iterable,Python,Python 3.x,Iterable,假设您使用包装器对象: 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.__ge
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)
此对象实现了\uu iter\uu
,因为它将对它的任何调用传递给实现它的成员f
。例如:
>>> x = IterOrNotIter()
>>> x.__iter__().__next__()
'Whatever was in /tmp/toto.txt\n'
根据文档(),IterOrNotIter因此应该是可移植的
但是,Python解释器无法将IterOrNotIter
对象识别为实际可移植的对象:
>>> 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
我不明白为什么。基本上是因为您的类没有真正的
\uuu iter\uuu
方法:
>>> hasattr(IterOrNotIter, '__iter__')
False
因此,它不符合迭代器的条件,因为对\uuuuu iter\uuuu
的实际检查是检查是否存在,而不是假设它已实现。因此,使用\uuuu getattr\uuuu
或\uuuu getattribute\uuuuu
的变通方法(不幸的是)不起作用
这实际上在以下文件中提到:
注
当通过语言语法或内置函数进行隐式调用后查找特殊方法时,仍然可以忽略此方法。看
后一节还解释了原因:
以这种方式绕过\uuuu getattribute\uuuu()
机器,为解释器内的速度优化提供了很大的空间,但代价是在处理特殊方法时有一定的灵活性(必须在类对象本身上设置特殊方法,以便解释器一致地调用它))
强调我的。好吧,这让人失望。解释器检查而不是仅仅调用的事实让人觉得不和谐。@user589082是的,有点不和谐,但根据文档(我更新了答案)对于特殊的方法,这会使Python的速度大大加快,但会牺牲灵活性。@MSeifert:ok,但文档应该明确警告,在不可iterable对象上尝试使用monkey patch
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu和\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,修补的方法将被忽略,对象将引发异常并失败。否则,这是违反代码意图的不明显的“神奇”行为。@smci Python有一个问题跟踪程序。您可以要求对相关文件进行修订/澄清。
>>> hasattr(IterOrNotIter, '__iter__')
False