Python Numbers¶
Number Types¶
int
: integral numberfloat
: floating point number, usually IEEE 754 (64 bits, base 2)complex
: complex number, implemented as two floatsdecimal.Decimal
: floating point number stored in base 10, arbitrary precisionfractions.Fraction
: rational, numerator/denominator; automatically compute the greatest common divisor (GCD) to simplify the fraction
Number Tower¶
The numbers module is specified by the PEP 3141 – A Type Hierarchy for Numbers.
numbers.Number: base class
numbers.Complex: Add
real
,imag
,conjugate()
numbers.Real: subclass of Complex; add many float operations.
numbers.Rational: subclass of Real; add
numerator
anddenominator
attributesnumbers.Integral: subclass of Rational
Subclasses:
numbers.Number: int, float, complex, decimal.Decimal, fractions.Fraction
numbers.Complex: int, float, complex, fractions.Fraction
numbers.Real: int, float, fractions.Fraction
numbers.Rational: int, fractions.Fraction
numbers.Integral: int
int, float, complex methods and attributes:
conjugate()
imag
real
int and Fraction attributes:
denominator
numerator
Conversions in Python¶
int(obj)
and float(obj)
accept:
int
float
decimal.Decimal
fractions.Fraction
bytes
str
int(obj)
rounds towards zero (ROUND_DOWN, ex: int(0.9) == 0
and
int(-0.9) == 0
).
But int(obj)
and float(obj)
reject:
complex
complex(obj)
accepts:
int
float
complex
decimal.Decimal
fractions.Fraction
str
But complex(obj)
rejects:
bytes
decimal.Decimal(obj)
accepts:
int
float
decimal.Decimal
str
But decimal.Decimal(obj)
rejects:
complex
fractions.Fraction
bytes
fractions.Fraction(obj)
accepts:
int
float
decimal.Decimal
fractions.Fraction
str
(ex:"1"
or"1/2"
)
But fractions.Fraction(obj)
rejects:
complex
bytes
int type¶
Examples:
>>> (123).bit_length()
7
>>> sys.int_info
sys.int_info(bits_per_digit=30,
sizeof_digit=4)
Serialization as bytes:
>>> (123).to_bytes(4, 'little')
b'{\x00\x00\x00'
>>> int.from_bytes(b'{\x00\x00\x00', 'little')
123
Rounding:
int(float)
callsfloat.__trunc__()
, so rounds towards zero (ROUND_DOWN)
float type¶
Examples:
>>> sys.float_info
sys.float_info(max=1.7976931348623157e+308,
max_exp=1024,
max_10_exp=308,
min=2.2250738585072014e-308,
min_exp=-1021,
min_10_exp=-307,
dig=15,
mant_dig=53,
epsilon=2.220446049250313e-16,
radix=2,
rounds=1)
>>> sys.float_repr_style
'short'
>>> (1.2).as_integer_ratio()
(5404319552844595, 4503599627370496)
Formatting as hexadecimal (base 16):
>>> (1.1).hex()
'0x1.199999999999ap+0'
>>> float.fromhex('0x1.199999999999ap+0')
1.1
Rounding:
float.__trunc__(): Round towards zero (ROUND_DOWN)
float.__round__(): Round to nearest with ties going to nearest even integer (ROUND_HALF_EVEN).
float.__int__() is an alias to float.__trunc__() (ROUND_DOWN)
Fraction¶
>>> fractions.Fraction(5, 10) # int / int
Fraction(1, 2)
>>> fractions.Fraction(1.2) # float
Fraction(5404319552844595, 4503599627370496)
C API¶
Convert a Python object to an integer. Type methods:
__int__()
: slottype->tp_as_number->nb_int
__index__()
: slottype->tp_as_number->nb_index
__trunc__()
(no slot)
PyNumber_Long(obj)
:
Call
obj.__trunc__()
(Round towards zero, ROUND_DOWN)or: If
obj
type is bytes or str, parse the string in decimal (base 10)or: error!
PyNumber_Index(x)
calls the __index__()
method: raises an exception if
the type has no __index__()
method or if method does not return exactly an
int type (*).
_PyLong_FromNbInt(x)
:
Call
type(x).__int__(x)
: the result type must be exactly the int type (*)or: error!
_PyLong_FromNbIndexOrNbInt(x)
: __index__()
or __int__()
:
return
x
iftype(x) == int
(PyLong_CheckExact()
)call
type(x).__index__(x)
if defined: the result type must be exactly the int type (*)call
type(x).__int__(x)
(call_PyLong_FromNbInt()
): the result type must be exactly the int type (*)error if it is not a int subclass, and the type don’t define
__index__()
nor__int__()
methodNew in Python 3.8
PyLong_AsLong()
converts a Python int
to a C long
:
call
_PyLong_FromNbIndexOrNbInt()
raise OverflowError if the result does not fit into a C long
Python 3.7 and older only calls
__int__()
, not__index__()
.
PyLong_AsUnsignedLongMask()
converts a Python object to a C unsigned
long
:
call
_PyLong_FromNbIndexOrNbInt(x)
and then_PyLong_AsUnsignedLongMask()
on the resulterror if the object cannot be converted to an int by
_PyLong_FromNbIndexOrNbInt(x)
mask integer overflow
Python 3.7 and older only calls
__int__()
, not__index__()
.
(*) Special case: __int__()
or __index__()
return a int subclass. This
feature is deprecated since Python 3.3 (see commit 6a44f6ee).
This feature may be removed from Python 3.9: see bpo-17576.
PyArg_ParseTuple and Py_BuildValue¶
Reference documentation: Parsing arguments and building values.
PyArg_ParseTuple is implemented in
Python/getargs.c
, core function:convertsimple()
.Py_BuildValue is implemented in
Python/modsupport.c
, core function:do_mkvalue()
.Functions behave differently if
PY_SSIZE_T_CLEAN
is defined:For all
#
variants of formats (s#
,y#
, etc.), the type of the length argument (int orPy_ssize_t
) is controlled by defining the macroPY_SSIZE_T_CLEAN
before includingPython.h
.
PyArg_ParseTuple formats:
"i"
(Cint
):__index__()
or__int__()
; callPyLong_AsLong(obj)
, but explicitly rejects float usingPyFloat_Check(arg)
."l"
(Clong
):__index__()
or__int__()
; callPyLong_AsLong()
, but explicitly rejects float usingPyFloat_Check(arg)
"n"
(Cssize_t
):__index__()
; callPyNumber_Index()
and thenPyLong_AsSsize_t()
. Exception on overflow."k"
: callPyLong_AsUnsignedLongMask()
if it’s an int or int subclass, error otherwise. Mask integer overflow.
Note: In Python 3.7 and older, PyLong_AsLong()
only calls __int__()
,
not __index__()
.
Script to update this page¶
number_tower.py:
from __future__ import print_function
import numbers
import warnings
import fractions
import decimal
warnings.simplefilter("error", DeprecationWarning)
VALUES = (
("int", 123),
("float", 1.5),
("complex", complex(0, 1.5)),
("decimal.Decimal", decimal.Decimal("1.1")),
("fractions.Fraction", fractions.Fraction(1, 7)),
("bytes", b"123"),
("str", "123"),
)
TYPES = (
("int", int),
("float", float),
("complex", complex),
("decimal.Decimal", decimal.Decimal),
("fractions.Fraction", fractions.Fraction),
)
for type_descr, num_type in TYPES:
accepted = []
rejected = []
for value_descr, value in VALUES:
try:
num_type(value)
except TypeError:
rejected.append(value_descr)
else:
accepted.append(value_descr)
if accepted:
print("``%s(obj)`` accept:" % type_descr)
print()
for name in accepted:
print("* ``%s``" % name)
print()
if rejected:
print("``%s(obj)`` reject:" % type_descr)
print()
for name in rejected:
print("* ``%s``" % name)
print()
print()
for tower_name, tower_type in (
("Number", numbers.Number),
("Complex", numbers.Complex),
("Real", numbers.Real),
("Rational", numbers.Rational),
("Integral", numbers.Integral),
):
subclasses = []
for type_descr, num_type in TYPES:
if issubclass(num_type, tower_type):
subclasses.append(type_descr)
print("%s subclasses: %s" % (tower_name, ", ".join(subclasses)))