An integer increments to a long, but not vice versa in Python. What for?

When the value of a number is outside the range of the integer , python moves it to long . But when the value returns to the integer range, why doesn't it drop to int level?

 >>> i=2147483647 >>> type(i) <type 'int'> >>> i = i + 1 >>> type(i) <type 'long'> >>> i = i - 10 >>> type(i) <type 'long'> >>> i 2147483638L >>> 
+4
source share
3 answers

From a python source (in the Objects / longobject.c file):

 static PyLongObject * x_add(PyLongObject *a, PyLongObject *b) { Py_ssize_t size_a = ABS(a->ob_size), size_b = ABS(b->ob_size); PyLongObject *z; int i; digit carry = 0; /* Ensure a is the larger of the two: */ if (size_a < size_b) { { PyLongObject *temp = a; a = b; b = temp; } { Py_ssize_t size_temp = size_a; size_a = size_b; size_b = size_temp; } } z = _PyLong_New(size_a+1); if (z == NULL) return NULL; for (i = 0; i < size_b; ++i) { carry += a->ob_digit[i] + b->ob_digit[i]; z->ob_digit[i] = carry & MASK; carry >>= SHIFT; } for (; i < size_a; ++i) { carry += a->ob_digit[i]; z->ob_digit[i] = carry & MASK; carry >>= SHIFT; } z->ob_digit[i] = carry; return long_normalize(z); } /* Subtract the absolute values of two integers. */ static PyLongObject * x_sub(PyLongObject *a, PyLongObject *b) { Py_ssize_t size_a = ABS(a->ob_size), size_b = ABS(b->ob_size); PyLongObject *z; Py_ssize_t i; int sign = 1; digit borrow = 0; /* Ensure a is the larger of the two: */ if (size_a < size_b) { sign = -1; { PyLongObject *temp = a; a = b; b = temp; } { Py_ssize_t size_temp = size_a; size_a = size_b; size_b = size_temp; } } else if (size_a == size_b) { /* Find highest digit where a and b differ: */ i = size_a; while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i]) ; if (i < 0) return _PyLong_New(0); if (a->ob_digit[i] < b->ob_digit[i]) { sign = -1; { PyLongObject *temp = a; a = b; b = temp; } } size_a = size_b = i+1; } z = _PyLong_New(size_a); if (z == NULL) return NULL; for (i = 0; i < size_b; ++i) { /* The following assumes unsigned arithmetic works module 2**N for some N>SHIFT. */ borrow = a->ob_digit[i] - b->ob_digit[i] - borrow; z->ob_digit[i] = borrow & MASK; borrow >>= SHIFT; borrow &= 1; /* Keep only one sign bit */ } for (; i < size_a; ++i) { borrow = a->ob_digit[i] - borrow; z->ob_digit[i] = borrow & MASK; borrow >>= SHIFT; borrow &= 1; /* Keep only one sign bit */ } assert(borrow == 0); if (sign < 0) z->ob_size = -(z->ob_size); return long_normalize(z); } 

Note that the return types of both PyLongObject * procedures.

This shows that adding and subtracting long gives more long in python, regardless of whether the values ​​can match in ints.

Example:

 >>> 3L + 4L 7L 

And here are the python enforcement rules, in particular:

For objects x and y, the first x.__add__(y) . If this is not implemented or NotImplemented returned, y.__add__(x) . If this also fails or returns NotImplemented, a TypeError exception.

So i - 10 , where i is long , leads to another long .

+1
source

Advancing int to long does not lose any information and it is necessary to store large numbers.

Demoting is not required and will not have any real benefits other than saving 4 bytes of memory, which is not really a priority in the interpreted language.

+4
source

As additional evidence that the python development team is thinking of int vs long, in python 3 int and long are unified.

http://docs.python.org/release/3.0.1/whatsnew/3.0.html#integers

+1
source

Source: https://habr.com/ru/post/1394206/


All Articles