[Python-Dev] Semantics of __int__(), __index__()

Oscar Benjamin oscar.j.benjamin at gmail.com
Thu Apr 4 16:23:38 CEST 2013


On 4 April 2013 10:39, Hrvoje Niksic <hrvoje.niksic at avl.com> wrote:
>
>> On Wed, Apr 3, 2013 at 6:47 AM, Hrvoje Niksic <hrvoje.niksic at avl.com>
>> wrote:
>>>
>>> It seems like a good feature that an __int__ implementation can choose to
>>> return an int subclass with additional (and optional) information. After
>>> all, int subclass instances should be usable everywhere where ints are,
>>> including in C code.
[SNIP]
>
> The typical reason to subclass int is to add more information or new methods
> on the instance, not to break basic arithmetic. Doing anything else breaks
> subtitutability and is well outside the realm of "consenting adults".
> Someone who wants to change basic arithmetic is free to implement an
> independent int type.

The reason for calling int(obj) is to get an object that is precisely
of type int. When I call this I do not want any modified or additional
methods or data attached to the resulting object.

The example given at the start of the thread makes minimal
modifications in an int subclass but still allows the result of
int(obj) to be unpickleable:

>>> class Int1(int):
...     def __int__(self):
...         return self
...
>>> n = Int1(4)
>>> n
4
>>> import pickle
>>> ni = int(n)
>>> pickle.dumps(ni)
... snip ...
  File "q:\tools\Python27\lib\pickle.py", line 562, in save_tuple
    save(element)
  File "q:\tools\Python27\lib\pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "q:\tools\Python27\lib\pickle.py", line 401, in save_reduce
    save(args)
  File "q:\tools\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "q:\tools\Python27\lib\pickle.py", line 562, in save_tuple
    save(element)
  File "q:\tools\Python27\lib\pickle.py", line 291, in save
    issc = issubclass(t, TypeType)
RuntimeError: maximum recursion depth exceeded while calling a Python object

I don't know whether that's a bug in pickle, but I think it's fair to
say that there are times when someone wants an object that is
precisely of type int. They should be able to rely on int(obj)
returning an int or raising an error.

This is true similarly for __index__. The entire purpose of __index__
is to permit APIs like list.__getitem__ to work extensibly with any
int-like object. This is achieved by allowing any object to advertise
its convertibility from an int-like object to an int with the same
numeric value. Anyone who calls operator.index(obj) is explicitly
stating that they do not want any property of obj apart from its
integer value and that they want that as an int. That it should be an
object of type int is explicitly stated in PEP 357
(http://www.python.org/dev/peps/pep-0357/):
"""
 2) The __index__ special method will have the signature

       def __index__(self):
           return obj

       where obj must be either an int or a long.
"""


Oscar


More information about the Python-Dev mailing list