La documentation Python indique clairement que x==y
appelle x.__eq__(y)
. Cependant, il semble que dans de nombreuses circonstances, le contraire soit vrai. Où est-il documenté quand ou pourquoi cela se produit, et comment puis-je savoir avec certitude si l'objet __cmp__
o __eq__
vont être appelées.
Edit : Juste pour clarifier, je sais que __eq__
est appelé en préférence à __cmp__
mais je ne comprends pas bien pourquoi y.__eq__(x)
est appelé de préférence à x.__eq__(y)
alors que c'est ce qui se passe selon la documentation.
>>> class TestCmp(object):
... def __cmp__(self, other):
... print "__cmp__ got called"
... return 0
...
>>> class TestEq(object):
... def __eq__(self, other):
... print "__eq__ got called"
... return True
...
>>> tc = TestCmp()
>>> te = TestEq()
>>>
>>> 1 == tc
__cmp__ got called
True
>>> tc == 1
__cmp__ got called
True
>>>
>>> 1 == te
__eq__ got called
True
>>> te == 1
__eq__ got called
True
>>>
>>> class TestStrCmp(str):
... def __new__(cls, value):
... return str.__new__(cls, value)
...
... def __cmp__(self, other):
... print "__cmp__ got called"
... return 0
...
>>> class TestStrEq(str):
... def __new__(cls, value):
... return str.__new__(cls, value)
...
... def __eq__(self, other):
... print "__eq__ got called"
... return True
...
>>> tsc = TestStrCmp("a")
>>> tse = TestStrEq("a")
>>>
>>> "b" == tsc
False
>>> tsc == "b"
False
>>>
>>> "b" == tse
__eq__ got called
True
>>> tse == "b"
__eq__ got called
True
Edit : D'après la réponse et le commentaire de Mark Dickinson, il semblerait que :
- Remplacement de la comparaison riche
__cmp__
-
__eq__
c'est son propre__rop__
à son__op__
(et similaire pour__lt__
,__ge__
etc) - Si l'objet de gauche est une classe intégrée ou de style nouveau, et que l'objet de droite est une sous-classe de celle-ci, l'attribut
__rop__
est essayée avant que l'objet de gauche__op__
Cela explique le comportement dans le TestStrCmp
exemples. TestStrCmp
est une sous-classe de str
mais n'implémente pas sa propre __eq__
donc le __eq__
de str
a la priorité dans les deux cas (c'est-à-dire tsc == "b"
appelle b.__eq__(tsc)
comme un __rop__
en raison de la règle 1).
Dans le TestStrEq
exemples, tse.__eq__
est appelé dans les deux cas car TestStrEq
est une sous-classe de str
et c'est ainsi qu'on l'appelle de préférence.
Dans le TestEq
exemples, TestEq
met en œuvre __eq__
y int
ne le fait pas. __eq__
est appelé les deux fois (règle 1).
Mais je ne comprends toujours pas le tout premier exemple avec TestCmp
. tc
n'est pas une sous-classe de int
donc AFAICT 1.__cmp__(tc)
devrait être appelé, mais ne l'est pas.