__getattr__ does not work with __enter__ & # 8594; AttributeError

I would like to use with for an object that uses __getattr__ to redirect calls.
Howerver, it looks like this is not working with the __enter__ method

Please consider the following simplified code to reproduce the error:

 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 

Output:

 <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__ 

Why doesn't it return to __getattr__ since __enter__ does not exist on the object?

Of course, I could make it work if I just create the __enter__ method and redirect there instead, but I wonder why this is not working.

My python version is as follows:

 C:\Python27\python27.exe 2.7 (r27:82525, Jul 4 2010, 07:43:08) [MSC v.1500 64 bit (AMD64)] 
+4
source share
2 answers

According to the above, this work was a bug in 2.6, which was "fixed" in 2.7. The short answer is that methods like __enter__ looked up by the class, not the object.

The documentation for this obscure behavior is at http://docs.python.org/reference/datamodel#specialnames : x[i] is roughly equivalent to ... type(x).__getitem__(x, i) for new-style classes .

This behavior can be seen using other special methods:

 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 

First work; second, no. Python 2.6 did not match this behavior for __enter__ and __exit__ , but 2.7 does. http://bugs.python.org/issue9259

However, it is painfully incompatible that these methods cannot be processed dynamically, like any other attributes. Similarly, you cannot access these methods with __getattribute__ , like any other method. I can not find the logic of the design logic. Python is usually very consistent and it's a pretty nasty wart.

+3
source

What version of python are you using? This seems to be an old mistake. Take a look at this one . Your code works with Python 2.5.1 (r251:54863, Feb 6 2009, 19:02:12) with a fixed def __exit__(self, *args):

0
source

All Articles