|
|
|
also happens when you try to override __call__ by replacing it directly:
>>> def say():
... return "hello world"
...
>>> say.__call__ = lambda: 'goodbye world'
>>> say()
'hello world'
>>> say.__call__()
'goodbye world'
>>> say.__dict__
{'__call__': <function <lambda> at 0xa7d04c34>}
Ido |
07/04/30 - 12:58 am | #
|
|
Yes this has been a huge pain in my side through the super discussions, especially in trying to keep in backwards-compatible.
Also, I have no idea where the language defines this behavior.
Calvin Spealman |
Homepage |
07/04/30 - 4:05 am | #
|
|
Ah, I figured out the why, here.
X() is an operation, and most operations that can be overridden by a method actually dont do the method lookup on the object, X, but on its type. This is an optimization, skipping the dict lookup on the object and going straight to the classes in the MRO.
Thats why you get the normal __call__ method when you do X(), because the method is found on the type, where the __getattribute__ doesnt get invoked. But, when you do X.__call__(), at the attribute lookup the __getattribute__ comes into play and you call what it returns.
Calvin Spealman |
Homepage |
07/04/30 - 4:21 am | #
|
|
Yeah - special methods are looked up on the class. This is why you override special method lookups on *classes* on the *metaclass*.
Fuzzyman |
Homepage |
07/04/30 - 9:27 pm | #
|
|
|
Commenting by HaloScan
|