[Tutor] True and 1 [was Re: use of the newer dict types]

Albert-Jan Roskam fomcl at yahoo.com
Thu Aug 1 21:28:35 CEST 2013



----- Original Message -----

> From: eryksun <eryksun at gmail.com>
> To: Albert-Jan Roskam <fomcl at yahoo.com>
> Cc: "tutor at python.org" <tutor at python.org>
> Sent: Wednesday, July 31, 2013 4:16 PM
> Subject: Re: [Tutor] True and 1 [was Re: use of the newer dict types]
> 
> On Mon, Jul 29, 2013 at 7:33 AM, Albert-Jan Roskam <fomcl at yahoo.com> 
> wrote:
>>  Wow, too bad __cmp__ is no longer present. Not so much for cmp(), but
>>  because it's such a compact way to define all the comparison methods.
>>  Btw, my book says "Python will supply the __ne__() (not equal)
>>  inequality operator automatically if wel implement __eq__ but don't
>>  implement __ne__()". [Programming in Python 3 (2009), M. Summerfield,
>>  p.213]
> 
> That's true in 3.x. The base object type has a default rich comparison
> that uses __eq__ to implement __ne__ (but not vice versa).
> 
> The CPython tp_richcompare slot function is object_richcompare in
> Objects/typeobject.c. Here's a link to 3.3.2:
> 
> http://hg.python.org/cpython/file/d047928ae3f6/Objects/typeobject.c#l3175
> 
> In 2.x the base object type doesn't implement rich comparisons. You'll
> get the default comparison in CPython (by id or type name), which
> won't necessarily be consistent with __eq__.
> 
> Here's something to riddle out. Why does CPython 2.x make 22 method
> calls for the following cmp()?
> 
>     class A(object):
>         def _print(self, op):
>             print '%s.__%s__' % (type(self).__name__, op)
>         def __eq__(self, other):
>             self._print('eq')
>             return NotImplemented
>         def __lt__(self, other):
>             self._print('lt')
>             return NotImplemented
>         def __gt__(self, other):
>             self._print('gt')
>             return NotImplemented
>         def __coerce__(self, other):
>             self._print('coerce')
>             return NotImplemented
> 
>     class B(A):
>         pass
> 
>     >>> cmp(A(), B())
>     B.__eq__
>     A.__eq__
>     A.__eq__
>     B.__eq__
>     B.__eq__
>     A.__eq__
>     B.__gt__
>     A.__lt__
>     A.__lt__
>     B.__gt__
>     B.__gt__
>     A.__lt__
>     B.__lt__
>     A.__gt__
>     A.__gt__
>     B.__lt__
>     B.__lt__
>     A.__gt__
>     A.__coerce__
>     B.__coerce__
>     B.__coerce__
>     A.__coerce__
>     -1

Six comparisons for each operator (6 x 3) and the 4 calls to __coerce__ seems much.
So you arrvie at 8 calls by 3 operator methods called  "bidirectionally" (A-B and B-A) + two calls to __coerce__?

> Why is the order BAABBA repeated 3 times? As a hint, I'll group it
> like this: BA--AB--BA.
> 
> Jython does this 'right' (IMHO) with 8 calls. PyPy appears to be
> playing tight to what's technically allowed and steps over the line.
> It only uses 4 calls, but it doesn't attempt a __coerce__, which I
> think is technically wrong.

I did "help(coerce)" and it seems straightforward, however, I can't connect it to your remark about coercion.
I thought pypy would behave differently with e.g cmp(1, "x"), compared to cpython

antonia at antonia-HP-2133 ~ $ pypy
Python 2.7.2 (1.9+dfsg-1, Jun 19 2012, 23:23:45)
[PyPy 1.9.0 with GCC 4.7.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
And now for something completely different: ``'that's definitely a case of
"uh????"'''
>>>> cmp(1, "x")
-1
>>>> cmp(1, 1.0)
0
>>>> cmp(-1, 1.0)
-1
>>>> quit()
antonia at antonia-HP-2133 ~ $ python
Python 2.7.3 (default, Apr 10 2013, 05:09:49) 
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> cmp(1, "x")
-1
>>> cmp(1, 1.0)
0
>>> cmp(-1, 1.0)
-1
# I was hoping this, I mean dis, would shed some light on this
>>> import dis
>>> dis.dis("cmp(0, 0)")
          0 DUP_TOPX        28781
          3 STORE_SLICE+0  
          4 <48>           
          5 <44>           
          6 SLICE+2        
          7 <48>           
          8 STORE_SLICE+1  
>>> dis.dis("cmp(0, 0.0)")
          0 DUP_TOPX        28781
          3 STORE_SLICE+0  
          4 <48>           
          5 <44>           
          6 SLICE+2        
          7 <48>           
          8 <46>           
          9 <48>           
         10 STORE_SLICE+1  


More information about the Tutor mailing list