Is 'everything' a refrence or isn't it?
Steven D'Aprano
steve at REMOVETHIScyber.com.au
Mon Jan 16 17:24:37 EST 2006
On Mon, 16 Jan 2006 21:18:35 +0000, Bengt Richter wrote:
> On Mon, 16 Jan 2006 21:58:26 +1100, Steven D'Aprano <steve at REMOVETHIScyber.com.au> wrote:
>
>>On Mon, 16 Jan 2006 10:34:40 +0000, Bengt Richter wrote:
>>
>>> >>> class A:
>>> ... def __getattr__(self, attr): print 'A().%s'%attr; raise AttributeError
>>> ...
>>> >>> class B:
>>> ... def __getattr__(self, attr): print 'B().%s'%attr; raise AttributeError
>>> ...
>>> >>> A()==B()
>>> A().__eq__
>>> B().__eq__
>>> B().__eq__
>>> A().__eq__
>>> A().__coerce__
>>> B().__coerce__
>>> A().__cmp__
>>> B().__cmp__
>>> False
>>
>>Why are A().__eq__ and B().__eq__ both being called twice?
>>
> I imagine it's trying the calls with args swapped or something like that.
> Want to write a test and see? (Don't hold your breath if you're waiting for me to do it ;-)
You already wrote a test. I can't think of any test I can write which
would give more information than yours. I'd like a test where I can see
the arguments which Python would apply to each method call, but I can't
think of any way to get those arguments inside the __getattr__ method.
Perhaps I'm not thinking hard enough.
(Actually writing __eq__ methods would defeat the purpose.)
There aren't that many possibilities. We can predict the other argument
from each call: if you call a method of A, the argument must be B and vice
versa. So it looks like Python is making the following calls:
A().__eq__(B)
B().__eq__(A)
B().__eq__(A)
A().__eq__(B)
followed by the unproblematic calls to __coerce__ and __cmp__.
What puzzles me is that after trying B.__eq__(A), it tries it again
immediately. It only calls coerce and cmp once with each set of args. What
am I missing?
--
Steven.
More information about the Python-list
mailing list