为什么我不能迭代通过__getattr__委托给可迭代的对象?

Roh*_*ain 5 python python-2.7

关于这个主题的核心Python编程一书中的一个例子Delegation似乎没有工作......或者可能是我没有清楚地理解这个主题..

下面是代码,其中类CapOpen包装file对象并定义filewrite模式下打开时的修改行为.它应该只在UPPERCASE中写入所有字符串.

但是,当我尝试打开文件进行读取,并迭代它以打印每一行时,我得到以下异常:

Traceback (most recent call last):
  File "D:/_Python Practice/Core Python Programming/chapter_13_Classes/
        WrappingFileObject.py", line 29, in <module>
    for each_line in f:
TypeError: 'CapOpen' object is not iterable
Run Code Online (Sandbox Code Playgroud)

这很奇怪,因为虽然我没有明确定义迭代器方法,但我希望将调用委托__getattr__给底层file对象.这是代码.我错过了什么吗?

class CapOpen(object):
    def __init__(self, filename, mode='r', buf=-1):
        self.file = open(filename, mode, buf)

    def __str__(self):
        return str(self.file)

    def __repr__(self):
        return `self.file`

    def write(self, line):
        self.file.write(line.upper())

    def __getattr__(self, attr):
        return getattr(self.file, attr)


f = CapOpen('wrappingfile.txt', 'w')
f.write('delegation example\n')
f.write('faye is good\n')
f.write('at delegating\n')
f.close()

f = CapOpen('wrappingfile.txt', 'r')

for each_line in f:   # I am getting Exception Here..
    print each_line,
Run Code Online (Sandbox Code Playgroud)

我使用的是Python 2.7.

ire*_*ses 12

这是针对新式类的Python 实现决策的非直观结果:

除了为了正确性而绕过任何实例属性之外,隐式特殊方法查找通常也会绕过__getattribute__()对象的元类的方法...

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

__getattr__/__getattribute__的文档中也明确指出了这一点:

注意 当通过语言语法或内置函数进行隐式调用查找特殊方法时,仍可以绕过此方法.请参阅新样式类的特殊方法查找.

换句话说,__getattr__当您的属性未定义时,您不能依赖于始终拦截您的方法查找.这不直观,因为期望这些隐式查找遵循与访问对象的所有其他客户端相同的路径是合理的.如果您f.__iter__直接从其他代码调用,它将按预期解析.但是,直接从语言调用时情况并非如此.

你引用的书很旧,所以原始的例子可能使用了旧式的类.如果从中删除继承object,则代码将按预期工作.话虽这么说,你应该避免编写旧样式类,因为它们将在Python 3中过时.如果你愿意,你仍然可以通过实现__iter__并立即委托底层来维护委托样式self.file.__iter__.

或者,file直接从对象继承并__iter__通过正常查找可用,这样也可以.