Принудительная копия маленького int в Python - PullRequest
2 голосов
/ 03 марта 2020

Как игрушечная проблема, я пытался придумать объекты a, b такие, что

type(a) == type(b) == int # True
a + 1 == b + 1 == 1       # True
a is b                    # False

Кажется, что deepcopy возвращается к _deepcopy_atomic, как обсуждалось здесь .

Можно ли создать копию маленького целого в Python?

Ответы [ 5 ]

2 голосов
/ 10 марта 2020

Да, это возможно, и без хаков или читов низкого уровня:

>>> a = 0
>>> b = 9**99 % 9**99
>>> type(a) == type(b) == int
True
>>> a + 1 == b + 1 == 1
True
>>> a is b
False

Я делаю это локально с Python 3.8.1, но вы также можете воспроизвести его в ответ .it и при www.python.org/shell/.

Для небольших позитивов:

>>> a = 7
>>> b = (9**99 + a) % 9**99
>>> b, type(b), a == b, a is b
(7, <class 'int'>, True, False)

Для небольших негативов:

>>> a = -2
>>> b = (9**99 + a) % -9**99
>>> b, type(b), a == b, a is b
(-2, <class 'int'>, True, False)
2 голосов
/ 07 марта 2020

Это, вероятно, не является целью вопроса, но 3 утверждения в вопросе могут быть удовлетворены, если разрешено переопределение int, так что пройдет следующий код:

int = type('', (int,), dict(vars(int)))
a = int(0)
b = int(0)
assert type(a) == type(b) == int
assert a + 1 == b + 1 == 1
assert a is not b
2 голосов
/ 06 марта 2020

Ответ на ваш вопрос зависит от того, что вы считаете small int . Согласно документации :

Текущая реализация хранит массив целочисленных объектов для всех целых чисел от -5 до 256, когда вы создаете int в этом диапазоне, вы фактически просто возвращаетесь ссылка на существующий объект.

В случае целых чисел строка a is b эквивалентна id(a) == id(b). Для диапазона [-5, 256] идентификаторы для всех чисел предопределены, что означает, что a и b действуют как псевдонимы для существующего объекта.

Единственный способ, которым a, b удовлетворит ваш условие a + 1 == b + 1 == 1 - это когда a = b = 0. Поскольку 0 находится в вышеупомянутом диапазоне, невозможно сделать a is b return False.

0 голосов
/ 06 марта 2020

Я смог заставить следующее работать на CPython:

import ctypes

x = 2
y = 3

ctypes.c_int.from_address(id(y) + 24).value = x

print(x == y) # True
print(x is y) # False

Я не мог обойтись без x = 0 или x = 1 без сбоя переводчика.

0 голосов
/ 03 марта 2020

Я не уверен, какие значения a и b вы использовали. Но для python вы можете просто использовать a = b, и это будет копия, потому что они являются примитивными типами в C, однако это работает только для маленьких целых чисел, так как большие целые числа преобразуются в другой тип в C, и больше не работы.

...