[Python-3000] A plus for naked unbound methods

Terry Reedy tjreedy at udel.edu
Tue Oct 7 17:44:24 CEST 2008


Nick Coghlan wrote:
> (added Michael to the CC list)
> 
> It isn't object that has grown an __lt__ method, but type. The extra
> check Michael actually wants is a way to make sure that the method isn't
> coming from the object's metaclass, and the only reliable way to do that
> is the way collections.Hashable does it when looking for __hash__:
> iterate through the MRO looking for that method name in the class
> dictionaries

Thank you for the explanation.  I was aware that MRO traversal should be 
the 'officially correct' procedure for the original, but did not 
understand why (for 2.x, at least).

> In the case of the comparison methods, they're being retrieved from type
> rather than object. This difference is made clear when you attempt to
> invoke the retrieved method:
> 
>>>> object.__cmp__(1, 2)
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: expected 1 arguments, got 2
>>>> object.__cmp__(2)
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: type.__cmp__(x,y) requires y to be a 'type', not a 'int'
>>>> object.__cmp__(object)
> 0

This surprises me, partly because the situation seems to be different in 
3.0.  Using __le__ in place of the non-existent __cmp__,

 >>> ole = object.__le__
 >>> ole(1,2)
NotImplemented
 >>> ole(1)
Traceback (most recent call last):
   File "<pyshell#21>", line 1, in <module>
     ole(1)
TypeError: expected 1 arguments, got 0
 >>> ole(object)
Traceback (most recent call last):
   File "<pyshell#22>", line 1, in <module>
     ole(object)
TypeError: expected 1 arguments, got 0
 >>> ole
<slot wrapper '__le__' of 'object' objects>
 >>> dir(ole)
['__call__', '__class__', '__delattr__', '__doc__', '__eq__', 
'__format__', '__ge__', '__get__', '__getattribute__', '__gt__', 
'__hash__', '__init__', '__le__', '__lt__', '__name__', '__ne__', 
'__new__', '__objclass__', '__reduce__', '__reduce_ex__', '__repr__', 
'__setattr__', '__sizeof__', '__str__', '__subclasshook__']
# no __self__ attribute

 >>> class C(object): pass

 >>> C.__le__
<slot wrapper '__le__' of 'object' objects>
# same as for hash in 2.5

I interpret all this to mean that in 3.0, rich comparison *are* defined 
on and being retrieved from object.  Correct?

I presume the change is because in 3.0, everything is an instance of 
object, so all classes can inherit the common methods from object, 
whereas that was *not* true in 2.x.  I very much like the cleaner design.

Terry Jan Reedy



More information about the Python-3000 mailing list