python - 为什么 __getattr__ 不能与 __exit__ 一起使用?

标签 python attr with-statement

在尝试计算另一个 question 时,我有点惊讶地发现了这一点。 .

这对我来说似乎非常奇怪,我认为值得问这个问题。为什么 __getattr__ 似乎不能与 with 一起使用?

如果我制作这个对象:

class FileHolder(object):
    def __init__(self,*args,**kwargs):
        self.f= file(*args,**kwargs)

    def __getattr__(self,item):
        return getattr(self.f,item)

并将其与 with 一起使用,

>>> a= FileHolder("a","w")
>>> a.write
<built-in method write of file object at 0x018D75F8>
>>> with a as f:
...   print f
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: __exit__
>>> a.__exit__
<built-in method __exit__ of file object at 0x018D75F8>

为什么会这样?

编辑

>>> object.__exit__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'object' has no attribute '__exit__'

肯定不是继承__exit__

最佳答案

with 语句操作码 SETUP_WITH 查找 __exit__ 作为“特殊方法查找”,忽略 __getattr____getattribute__ 在新式类上(但不是在旧式类上)。参见 this mailing list thread有关更多信息,他们讨论了将特殊方法查找语义添加到 with (他们最终这样做了)。另见 special method lookup for new-style classes有关为什么以这种方式查找这些特殊方法的详细讨论。

特别是,特殊方法查找绕过类型对象上的__getattr__。因此,即使文档说该方法被查找为 type(mgr).__exit__,此代码也不起作用:

class M(type):
    def __getattr__(*args): return lambda: 0

class X(object):
    __metaclass__ = M

x = X()
type(x).__exit__ # works, returns a lambda

with x: pass # fails, AttributeError

关于python - 为什么 __getattr__ 不能与 __exit__ 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12632894/

相关文章:

python - 如何在 Pandas 中使用具有多索引的 map ?

python - Wagtail 从字段创建自定义 StreamField block ?

Javascript - 在上下文/范围中进行评估,无需使用此关键字而不使用 with 语句

jQuery 用字符串值替换 attr href

append - LevelDB 文件夹中的哪些文件是只能追加的?

PHP 相当于 Javascript "with"作用域语句

python - 为什么 __del__ 在 with block 的末尾被调用?

python - 如何使用 SqlAlchemy 顺序获取列中的所有值?

python - SQLAlchemy + PostgreSQL + PG 正则表达式

javascript - jQuery 中的 attr() 是否强制小写?