Python __iter__和for循环

时间:2011-03-14 15:49:14

标签: python for-loop iterable

据我了解,我可以在一个对象上使用for循环结构,并使用返回迭代器的__iter__方法。我有一个对象,我实现了以下__getattribute__方法:

def __getattribute__(self,name):
    if name in ["read","readlines","readline","seek","__iter__","closed","fileno","flush","mode","tell","truncate","write","writelines","xreadlines"]:
        return getattr(self.file,name)
    return object.__getattribute__(self,name)

我有一个这个类的对象a,发生以下情况:

>>> hasattr(a,"__iter__")
True
>>> for l in a: print l
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'TmpFile' object is not iterable
>>> for l in a.file: print l
...
>>>

所以python看到a有一个__iter__方法,但不认为它是可迭代的。我做错了什么?这是python 2.6.4。

2 个答案:

答案 0 :(得分:12)

有一个微妙的实现细节妨碍你:__iter__实际上不是一个实例方法,而是一个类方法。也就是说,obj.__class__.__iter__(obj)被调用,而不是obj.__iter__()

这是由于引擎优化,允许Python运行时更快地设置迭代器。这是必要的,因为迭代器尽可能快地非常重要。

无法为基础__getattribute__类型定义class,因此无法动态返回此方法。这适用于大多数__metamethods__;你需要写一个实际的包装器。

答案 1 :(得分:4)

某些特殊方法在创建类时已经过优化,以后无法添加或通过赋值覆盖。有关__getattribute__的{​​{3}},请参阅:

  

此方法可能仍被绕过   查找特殊方法作为   通过隐式调用的结果   语言语法或内置函数。

在这种情况下,您需要做的是提供转发呼叫的__iter__的直接实现:

def __iter__(self):
    return self.file.__iter__()