Is 'everything' a refrence or isn't it?
Bengt Richter
bokr at oz.net
Mon Jan 16 19:51:52 EST 2006
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?
>
Looks like it has to do with trying stuff with arguments switched?
This shows call and argumenst to method for whichever attribute access
is allowed to succeed after a count of failures...
>>> def test():
... global trial, which
... for which in xrange(9):
... print '\nwhich: %s'%which
... trial = 0
... A()==B()
...
>>> def nameof(x):return type(x).__getattribute__(x, '__class__').__name__
...
>>> def __eq__(x, y):
... print '__eq__(%s(), %s())'%(nameof(x), nameof(y)); return False
...
>>> def __cmp__(x, y):
... print '__cmp__(%s(), %s())'%(nameof(x), nameof(y)); return 0
...
>>> def __coerce__(x, y):
... print '__coerce__(%s(), %s())'%(nameof(x), nameof(y)); return None
...
>>> class A:
... def __getattr__(self, attr):
... global trial
... print '%s: A().%s'%(trial, attr)
... if trial!=which: trial+=1; raise AttributeError
... return globals()[attr].__get__(self, type(self))
...
>>> class B:
... def __getattr__(self, attr):
... global trial
... print '%s: B().%s'%(trial, attr)
... if trial!=which: trial+=1; raise AttributeError
... return globals()[attr].__get__(self, type(self))
...
>>> test()
which: 0
0: A().__eq__
__eq__(A(), B())
which: 1
0: A().__eq__
1: B().__eq__
__eq__(B(), A())
which: 2
0: A().__eq__
1: B().__eq__
2: B().__eq__
__eq__(B(), A())
which: 3
0: A().__eq__
1: B().__eq__
2: B().__eq__
3: A().__eq__
__eq__(A(), B())
which: 4
0: A().__eq__
1: B().__eq__
2: B().__eq__
3: A().__eq__
4: A().__coerce__
__coerce__(A(), B())
4: B().__coerce__
__coerce__(B(), A())
4: A().__cmp__
__cmp__(A(), B())
which: 5
0: A().__eq__
1: B().__eq__
2: B().__eq__
3: A().__eq__
4: A().__coerce__
5: B().__coerce__
__coerce__(B(), A())
5: A().__cmp__
__cmp__(A(), B())
which: 6
0: A().__eq__
1: B().__eq__
2: B().__eq__
3: A().__eq__
4: A().__coerce__
5: B().__coerce__
6: A().__cmp__
__cmp__(A(), B())
which: 7
0: A().__eq__
1: B().__eq__
2: B().__eq__
3: A().__eq__
4: A().__coerce__
5: B().__coerce__
6: A().__cmp__
7: B().__cmp__
__cmp__(B(), A())
which: 8
0: A().__eq__
1: B().__eq__
2: B().__eq__
3: A().__eq__
4: A().__coerce__
5: B().__coerce__
6: A().__cmp__
7: B().__cmp__
>>>
Regards,
Bengt Richter
More information about the Python-list
mailing list