3

据我了解,我可以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。

4

2 回答 2

12

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

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

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

于 2011-03-14T16:08:33.227 回答
4

某些特殊方法在创建类时进行了优化,以后无法添加或通过赋值覆盖。请参阅文档__getattribute__其中说:

由于通过语言语法或内置函数隐式调用而查找特殊方法时,仍可能绕过此方法。

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

def __iter__(self):
    return self.file.__iter__()
于 2011-03-14T16:12:49.157 回答