richcmpfunc semantics
David M. Cooke
cookedm+news at physics.mcmaster.ca
Thu Apr 7 16:16:36 EDT 2005
harold fellermann <harold.fellermann at upf.edu> writes:
> Thank you Greg,
>
> I figured most of it out in the meantime, myself. I only differ
> from you in one point.
>
>>> What has to be done, if the function is invoked for an operator
>>> I don't want to define?
>>
>> Return Py_NotImplemented. (Note that's return, *not* raise.)
>
> I used
>
> PyErr_BadArgument();
> return NULL;
>
> instead. What is the difference between the two and which one
> is to prefer.
If you do it your way you're a bad neighbour: If your object is the
first one (left-hand side) of the operator, it will prevent the other
object from handling the case if it can. This is the same advice as
for all of the other operators (__add__, etc.)
Consider the pure-python version:
class A:
def __init__(self, what_to_do='return'):
self.what_to_do = what_to_do
def __eq__(self, other):
print 'A.__eq__'
if self.what_to_do == 'return':
return NotImplemented
else:
raise Exception
class B:
def __eq__(self, other):
print 'B.__eq__'
return True
>>> a = A('return')
>>> b = B()
>>> a == b
A.__eq__
B.__eq__
True
>>> b == a
B.__eq__
True
>>> a == a
A.__eq__
A.__eq__
A.__eq__
A.__eq__
True
So the B class handles the case where A doesn't know what to do. Also
note the last case, where Python falls back on id() comparisions to
determine equality.
Now, compare with this:
>>> a = A('raise')
>>> b = B()
>>> a == b
A.__eq__
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "x.py", line 9, in __eq__
raise Exception
Exception
>>> b == a
B.__eq__
True
>>> a == a
A.__eq__
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "x.py", line 9, in __eq__
raise Exception
Exception
So now comparing A and B objects can fail. If you *know* A and B
objects can't be compared for equality, it'd be ok to raise a
TypeError, but that should be after a type test.
> Also, do you need to increment the reference count
> of Py_NotImeplemented before returning it?
Yes; it's a singleton like Py_None.
--
|>|\/|<
/--------------------------------------------------------------------------\
|David M. Cooke
|cookedm(at)physics(dot)mcmaster(dot)ca
More information about the Python-list
mailing list