在尝试计算另一个 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/