class foo(list):
def __eq__(self, other):
raise 'foo.__eq__ called'
>>> help(list.__eq__)
Help on wrapper_descriptor:
__eq__(...)
x.__eq__(y) <==> x==y
>>> [].__eq__(foo())
True
>>> [] == foo()
Traceback (most recent call last):
File "", line 1, in ?
File "", line 3, in __eq__
foo.__eq__ called
Help says those two statements should be equivalent. Why aren't they?

11 comments:
I think it's because when you do:
a == b
(where b is an object that contains the __eq__ method)
it means b.__eq__(a)
try
foo() == []
I think I know the answer, but I don't know if I should give it away so soon and ruin it for everyone else :) Someone on an earlier question gave a rot13 answer, so I'll do that too. Am I right?
Jura gur glcr bs gur bowrpg ba gur evtug-unaq fvqr bs n pbzcnevfba vf n fhoglcr bs gur glcr bs gur bowrpg ba gur yrsg-unaq fvqr, vgf evpu-pbzcnevfba shapgvbaf ner hfrq vafgrnq bs gubfr sebz gur yrsg-unaq fvqr, jura ninvynoyr, naq ersyrpgrq (< orpbzrf >, rgp, ohg == fgnlf gur fnzr). Nf sne nf V xabj, vg'f whfg n fcrpvny pnfr, ohg vg qbrf fbeg bs znxr
frafr jura lbh guvax nobhg ubj lbh'q hfhnyyl hfr fhoglcrf va guvf jnl.
Gur bgure bcrengvba, jurer lbh'ir gnxra gur __rd__ nggevohgr bs [] qverpgyl anghenyyl unf n qvssrerag erfhyg, fvapr gur zrgubq pubfra vf abg hc gb gur evpu-pbzcnevfba znpuvarel.
Although they are meant to be commutative (is that the right one?) they have to be defined so they are. The __eq__ of the left hand object gets called:
class hat( object ):
def __eq__(self , other ):
print "I am hat"
print "other is a %s" % ( other.__class__.__name__ )
return True
class tree( object ):
def __eq__(self , other ):
print "I am tree"
print "other is a %s" % ( other.__class__.__name__ )
return False
a = hat()
b = tree()
a == b
b == a
forgot to show the outcome of that code :-)
it prints:
I am hat
other is a tree
I am tree
other is a hat
I am not paying enough attention - that is the answer to something else... oops!
The real answer:
class hat( object ):
def __eq__(self , other ):
return NotImplemented
class tree( object ):
def __eq__(self , other ):
print "I am tree"
print "other is a %s" % ( other.__class__.__name__ )
return True
a = hat()
b = tree()
a == b
b == a
returns:
I am tree
other is a hat
I am tree
other is a hat
The NotImplemented forces it to try the other available __eq__()
mark: yeah, but list.__eq__() doesn't return NotImplemented! :)
Paul: you are correct. (Source for those curious about this and related esoterica: uggc://qbpf.clguba.bet/ers/pbrepvba-ehyrf.ugzy)
Also at http://docs.python.org/ref/coercion-rules.html
...
Sorry. Had to.
Post a Comment