Re: richcmpfunc semantics

2005-04-07 Thread David M. Cooke
harold fellermann <[EMAIL PROTECTED]> 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 "", 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 "", 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
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: richcmpfunc semantics

2005-04-07 Thread harold fellermann
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. Also, do you need to increment the reference count
of Py_NotImeplemented before returning it?
Thanks,
- harold -
--
I like pigs. Dogs look up to us. Cats look down to us.
Pigs treat us as equal.
-- Winston Churchill
--
http://mail.python.org/mailman/listinfo/python-list


Re: richcmpfunc semantics

2005-04-07 Thread Greg Ewing
harold fellermann wrote:
richcmpfunc compare(PyObject *,PyObject, int);
I supposed the two objects passed are the ones to be compared.
Yes.
What is the meaning of the integer argument? Does it specify the kind
of comparision operator (e.g. __eq__ or __le__), and if so, how?

<   0

<=  1
==  2   
!=  3   

>   4

>=  5

What is my richcmpfunc supposed to return? 0 or 1 indicating False or
True?
In the usual case, yes, although it can return any
Python object. Rich comparison doesn't impose any
semantics on the operations -- this is one of the
reasons for its existence.
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.)
Maybe there is some good documentation available, but I cannot find it.
I found most of this out by reading the source, I think.
--
Greg Ewing, Computer Science Dept,
University of Canterbury,   
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg
--
http://mail.python.org/mailman/listinfo/python-list


richcmpfunc semantics

2005-04-06 Thread harold fellermann
Hi all,
I want to implement rich comparision in an extension class. Problem is 
I cannot
find good documentation of the richcmpfunc semantics. Given the 
signature

richcmpfunc compare(PyObject *,PyObject, int);
I supposed the two objects passed are the ones to be compared.
What is the meaning of the integer argument? Does it specify the kind
of comparision operator (e.g. __eq__ or __le__), and if so, how?
What is my richcmpfunc supposed to return? 0 or 1 indicating False or
True? What has to be done, if the function is invoked for an operator
I don't want to define?
Maybe there is some good documentation available, but I cannot find it.
So, any references or help is appreciated.
Cheers,
- harold -
--
"Scientist are very good in answering the questions
they choose to answer."
-- Richard Alley
--
http://mail.python.org/mailman/listinfo/python-list