[Python-Dev] boxing and unboxing data types

Steven D'Aprano steve at pearwood.info
Mon Mar 9 05:12:44 CET 2015


On Sun, Mar 08, 2015 at 08:31:30PM -0700, Ethan Furman wrote:

> When data is passed from Python to a native library (such as in an O/S 
> call), how does the unboxing of data types occur?
[...]
> So the real question: anywhere in Python where an int is expected (for 
> lower-level API work), but not directly received, should __int__ (or 
> __index__) be called?  and failure to do so is a bug?

I think the answer is in the docs:

https://docs.python.org/3/reference/datamodel.html#object.__int__

Immediately below that __index__ is described, with this note:

    In order to have a coherent integer type class, when 
    __index__() is defined __int__() should also be defined, 
    and both should return the same value.


The PEP adding __index__ is also useful:

https://www.python.org/dev/peps/pep-0357/


My summary is as follows:

__int__ is used as the special method for int(), and it should coerce 
the object to an integer. This may be lossy e.g. int(2.999) --> 2 or may 
involve a conversion from a non-numeric type to integer e.g. int("2").

__index__ is used when the object in question actually represents an 
integer of some kind, e.g. a fixed-with integer. Conversion should be 
lossless and conceptually may be thought of a way of telling Python 
"this value actually is an int, even though it doesn't inherit from int" 
(for some definition of "is an int").

There's no built-in way of calling __index__ that I know of (no 
equivalent to int(obj)), but slicing at the very least will call it, 
e.g. seq[a:] will call type(a).__index__.

If you define __index__ for your class, you should also define __int__ 
and have the two return the same value. I would expect that an IntFlags 
object should inherit from int, and if that is not possible, practical 
or desirable for some reason, then it should define __index__ and 
__int__.

Failure to call __index__ is not necessarily a bug. I think it is 
allowed for functions to insist on an actual int, as slicing did for 
many years, but it is an obvious enhancement to allow such functions to 
accept arbitrary int-like objects.

Does that answer your questions?



-- 
Steve


More information about the Python-Dev mailing list