Python 为什么可以';迭代一个通过uu getattr uu委托给iterable的对象?

Python 为什么可以';迭代一个通过uu getattr uu委托给iterable的对象?,python,python-2.7,Python,Python 2.7,书中关于委派的例子似乎不起作用。。或者可能是我没有很清楚地理解这个话题 下面是代码,其中类CapOpen包装了文件对象,并定义了在写入模式下打开时文件的修改行为。它应该只写大写的所有字符串 但是,当我试图打开该文件进行读取,并对其进行迭代以打印每一行时,会出现以下异常: Traceback (most recent call last): File "D:/_Python Practice/Core Python Programming/chapter_13_Classes/

书中关于委派的例子似乎不起作用。。或者可能是我没有很清楚地理解这个话题

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

但是,当我试图打开该文件进行读取,并对其进行迭代以打印每一行时,会出现以下异常:

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

我使用的是Python 2.7。

这是Python的非直观结果:

除了为了 正确性,隐式特殊方法查找通常也会绕过 对象元类的
\uu getattribute\uu()
方法

以这种方式绕过
\uuuu getattribute\uuuu()
机器提供 译员内部速度优化的重要范围,在 在处理特殊方法时具有一定灵活性的成本 必须在类对象本身上设置特殊方法才能 一致地由解释器调用)

文件中也明确指出了这一点:

注意 在以下情况下查找特殊方法时,仍然可以忽略此方法: 通过语言语法或内置函数进行隐式调用的结果 功能。请参见新样式类的特殊方法查找

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

你引用的那本书很旧,所以可能使用了最初的例子。如果从
对象
中删除继承,代码将按预期工作。也就是说,您应该避免编写旧式类,因为它们在Python3中会过时。如果愿意,您仍然可以在这里通过实现
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
并立即委托给底层的
self.file.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu


或者,直接从
文件
对象继承,通过正常查找可以使用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,这样也可以工作。

对于要创建的对象,其类必须定义<

仅当从实例检索某个对象时才调用,但由于支持迭代的方法有多种,Python首先查看是否存在适当的方法

试试这个:

class Fake(object):
    def __getattr__(self, name):
        print "Nope, no %s here!" % name
        raise AttributeError

f = Fake()
for not_here in f:
    print not_here
如您所见,出现了相同的错误:
TypeError:“Fake”对象不可编辑

如果您这样做:

print '__getattr__' in Fake.__dict__
print '__iter__' in Fake.__dict__
print '__getitem__' in Fake.__dict__
您可以看到Python所看到的:既不存在
\uuuu iter\uuuu
也不存在
\uuuu getitem\uuuuuu
,因此Python不知道如何迭代它。虽然Python可以尝试然后捕获异常,但我怀疑它不能捕获异常的原因是捕获异常的速度相当慢


有关制作迭代器的多种方法,请参阅。

您需要一个
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。。。因为你犯了一个不可原谅的错误。。。只需返回self.file.\uu下一步\uuu()
这就是我要问的。。为什么我会出错??我原以为那会自动授权的。。顺便说一句,你的
self.file.\uuuu next\uuuu()
也不起作用..嗯。。。那就不确定了。。。我想那会有用的。。。对不起,这个问题和实例
dict
中的方法无关,但和
类中的方法无关。。我正在用那本书的最新版本。。而且它使用了新样式的类来解决它的问题。。无论如何,这是一个很好的解释。。我想我知道为什么会这样。。Thanks@ire_and_curses:添加了更多示例。好的,在仔细阅读文档之后,我现在认为我理解了。我已经修改了我的答案,并取消了对你的否决票,尽管我不认为在你所写的内容中绕过
getattr
的原因是很清楚的(如果Python真的想解决
\uu getattr\uuu
,它没有理由不能解决)。@ire\u和\u诅咒:谢谢你的研究,我很感激。我再次更新了我的答案,并给出了一个可能的原因,说明Python为什么不这样做。“它的类必须定义
\uuuu iter\uuuu
”,或者
\uuuuu getitem\uuuu
,这是一个后备方法。在这种情况下,迭代随着索引的增加而发生,直到抛出
indexer
print '__getattr__' in Fake.__dict__
print '__iter__' in Fake.__dict__
print '__getitem__' in Fake.__dict__