我想with在一个__getattr__用于重定向调用的对象上使用.
然而,这似乎不适用于该方法__enter__
请考虑以下简化代码重现错误:
class EnterTest(object):
def myenter(self):
pass
def __exit__(self, type, value, traceback):
pass
def __getattr__(self, name):
if name == '__enter__':
return self.myenter
enter_obj = EnterTest()
print getattr(enter_obj, '__enter__')
with enter_obj:
pass
Run Code Online (Sandbox Code Playgroud)
输出:
<bound method EnterTest.myenter of <__main__.EnterTest object at 0x00000000021432E8>>
Traceback (most recent call last):
File "test.py", line 14, in <module>
with enter_obj:
AttributeError: __enter__
Run Code Online (Sandbox Code Playgroud)
为什么它不回落到__getattr__因为__enter__没有在对象上存在吗?
当然,如果我只是创建一个__enter__方法并从那里重定向,我可以使它工作,但我想知道为什么它不起作用.
我的python版本如下:
C:\Python27\python27.exe 2.7 (r27:82525, Jul 4 2010, 07:43:08) [MSC v.1500 64 bit (AMD64)]
Run Code Online (Sandbox Code Playgroud)
据上游称,这项工作是 2.6 中的一个错误,已在 2.7 中“修复”。简而言之,类似的方法__enter__是在类上查找的,而不是在对象上查找的。
这种晦涩行为的文档位于http://docs.python.org/reference/datamodel#specialnames : x[i] is roughly equivalent to ... type(x).__getitem__(x, i) for new-style classes。
您可以使用其他特殊方法来查看此行为:
class foo(object):
def __iadd__(self, i):
print i
a = foo()
a += 1
class foo2(object):
def __getattr__(self, key):
print key
raise AttributeError
b = foo2()
b += 1
class foo3(object):
pass
def func(self, i):
print i
c = foo3()
c.__iadd__ = func
c += 1
Run Code Online (Sandbox Code Playgroud)
第一个作品;后两个则不然。Python 2.6 不符合__enter__和 的这种行为__exit__,但 2.7 符合。 http://bugs.python.org/issue9259
也就是说,这些方法无法像任何其他属性一样动态处理,这是令人痛苦的不一致。__getattribute__同样,您不能像使用任何其他方法那样检测对这些方法的访问。我找不到任何内在的设计逻辑。Python 通常非常一致,这是一个相当令人不快的缺点。
| 归档时间: |
|
| 查看次数: |
1147 次 |
| 最近记录: |