'Difference between int and numbers.Integral in Python

I'm trying to get a deeper understanding in Python's data model and I don't fully understand the following code:

>>> x = 1

>>> isinstance(x,int)
True

>>> isinstance(x,numbers.Integral)
True

>>> inspect.getmro(int)
(<type 'int'>, <type 'object'>)

>>> inspect.getmro(numbers.Integral)
(<class 'numbers.Integral'>, <class 'numbers.Rational'>, <class 'numbers.Real'>,
 <class 'numbers.Complex'>, <class 'numbers.Number'>, <type 'object'>)

Based on the above, it seems that int and number.Integral are not in the same hierarchy.

From the Python reference (2.6.6) I see

numbers.Integral - These represent elements from the mathematical set of integers (positive and negative).

What's the difference between int and numbers.Integral? Does it have something to do with the type int vs class numbers.Integral I see in the above output?



Solution 1:[1]

numbers defines a hierarchy of abstract classes that define operations possible on numeric types. See PEP 3141. The difference between int and Integral is that int is a concrete type that supports all the operations Integral defines.

Solution 2:[2]

Allow me to add two things:

isinstance(x,numbers.Integral)

also covers long and

isinstance(x, int)

does not. The numbers.Integral test would be closer to

isinstance(x, (int, long))

in Python 2 (Python 3 killed long for good.)

I prefer the test with numbers.Integral, because if you derive from int (or long), isinstance(y, numbers.Integral) will still be True.

Solution 3:[3]

In [34]: numbers.Integral ?
Type:           ABCMeta
Base Class:     <class 'abc.ABCMeta'>
String Form:    <class 'numbers.Integral'>
Namespace:      Interactive
File:           c:\python26\lib\numbers.py
Docstring:
    Integral adds a conversion to long and the bit-string operations.


In [35]: int ?
Type:           type
Base Class:     <type 'type'>
String Form:    <type 'int'>
Namespace:      Python builtin
Docstring:
    int(x[, base]) -> integer


In [36]: type(int) == type (numbers.Integral)
Out[36]: False

In [39]: issubclass(int, numbers.Integral)
Out[39]: True

Integral is an Abstract Base Class. int is a subclass of the ABCMeta Integral

Solution 4:[4]

TLDR: int is registered as a virtual subclass of numbers.Integral.

# numbers.py:380 (CPython 3.8)
Integral.register(int)

numbers.Integral is an abstract definition of what integral numbers must provide. int is a concrete implementation of integral numbers.


The isinstance and issubclass functions are not restricted to inheritance. For example, they can express structural type relations such as collections.abc.Iterable:

>>> class MyIterable:
...     def __iter__(self): ...
...
>>> issubclass(MyIterable, collections.abc.Iterable)
True

In fact, both isinstance and issubclass can be changed for each type. The standard library uses this to define Abstract Base Classes (ABC) support both concrete subclasses (via inheritance) and virtual subclasses (via cls.register(subclass)).

A virtual subclass is not related to its ABC via inheritance -- its method resolution order thus does not use the ABC. In specific, int does not inherit any methods for numbers.Integral. However, it does implement all public methods and operations required for numbers.Integral independently - thus satisfying the numbers.Integral definition.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Cat Plus Plus
Solution 2 Robert Siemer
Solution 3
Solution 4