Почему (0-6) -6 = Ложь? [Дубликат]

Possible Duplicate:
Python “is” operator behaves unexpectedly with integers

Сегодня я попытался отладить свой проект, и после нескольких часов анализа я получил следующее:

>>> (0-6) is -6
False

но,

>>> (0-5) is -5
True

Не могли бы вы объяснить мне, почему? Может быть, это какая-то ошибка или очень странное поведение.

> Python 2.7.3 (default, Apr 24 2012, 00:00:54) [GCC 4.7.0 20120414 (prerelease)] on linux2
>>> type(0-6) 
<type 'int'>
>>> type(-6) 
<type 'int'>
>>> type((0-6) is -6)
<type 'bool'>
>>> 
 Wug13 июл. 2012 г., 20:30
ну вот совершенно дурацкий
 LarsH13 июл. 2012 г., 22:11
Комментарий @Russel ударил по голове - проблема в том, что кто-то явно использовал & quot; is & quot; сравнить цифры и ожидал, что он будет функционировать как=неверное ожидание.
 Russell Borogove13 июл. 2012 г., 20:35
Что заставило вас использоватьis на первом месте? Это не то, что должно часто использоваться в Python, кромеis/is not None дело.

Ответы на вопрос(4)

is это не тест на равенство.== даст ожидаемые результаты.

Техническая причина такого поведения заключается в том, что реализация Python может обрабатывать разные экземпляры одного и того же постоянного значения как один и тот же объект или как разные объекты. Реализация Python, которую вы используете, выбирает, чтобы определенные небольшие константы совместно использовали один и тот же объект для экономии памяти. Вы не можете полагаться на то, что это поведение является одной и той же версией для версии или для разных реализаций Python.

 14 июл. 2012 г., 13:18
+1 Для разработчика, не являющегося Python, это лучше всего объясняет мне.
 13 июл. 2012 г., 20:41
& GT;is это не тест на равенство. Это.is это тест идентичности, чтобы увидеть, если два объекта являются одинаковыми. Просто так получилось, что в реализации CPython некоторые объекты int кэшируются.

что CPython кэширует несколько маленьких целых чисел и маленьких строк и присваивает каждому экземпляру этого объекта одинаковыеid().

(0-5) а также-5, имеет то же значение дляid()что не верно для0-6 а также-6

>>> id((0-6))
12064324
>>> id((-6))
12064276
>>> id((0-5))
10022392
>>> id((-5))
10022392

Аналогично для строк:

>>> x = 'abc'
>>> y = 'abc'
>>> x is y
True
>>> x = 'a little big string'
>>> y = 'a little big string'
>>> x is y
False

Подробнее о кэшировании строк читайте в:is operator behaves differently when comparing strings with spaces

 13 июл. 2012 г., 20:36
так почему-6 считается "большим" а также-5 не? Каковы квалификационные критерии для того, чтобы что-то было рассмотрено как "большое"?
 13 июл. 2012 г., 20:43
+1 за показ идентификаторов; Я как раз собирался добавить это к своему ответу.
 13 июл. 2012 г., 20:40
Для CPython от -5 до 256 являются «интернированными»; (Кэшируется). Это несколько произвольный выбор реализации. Если данный интернированный объект используется часто, это потенциально большая экономия памяти, но есть затраты на его интернирование (во время выполнения или в памяти), поэтому вы не хотите делать это для всего.
Решение Вопроса

ъекты, имеющие один и тот же адрес с CPython, таким образом,is тест проходит.

Этот артефакт подробно объясняется вhttp://www.laurentluce.com/posts/python-integer-objects-implementation/и мы могли бы проверить текущий исходный код вhttp://hg.python.org/cpython/file/tip/Objects/longobject.c.

A specific structure is used to refer small integers and share them so access is fast. It is an array of 262 pointers to integer objects. Those integer objects are allocated during initialization in a block of integer objects we saw above. The small integers range is from -5 to 256. Many Python programs spend a lot of time using integers in that range so this is a smart decision.

This is only an implementation detail of CPython and you shouldn't rely on this. Например,PyPy реализовалid целое число, чтобы вернуть себя, так(0-6) is -6 всегда верно, даже если они являются "разными объектами" внутри; это также позволяет вам настроить, включать ли это целочисленное кэширование, и даже устанавливать нижнюю и верхнюю границы. Но в целом объекты, полученные из разных источников, не будут идентичными. Если вы хотите сравнить равенство, просто используйте==.

 13 июл. 2012 г., 20:30
Это то, что я собирался сказать, но я не мог сказать это правильно. +1
 16 июл. 2012 г., 11:26
Обратите внимание, что PyPy имеет разные обещания, хотя (несмотря на отсутствие кэширования) -pypy.readthedocs.org/en/latest/…
 Dmitry Zagorulkin13 июл. 2012 г., 20:47
Спасибо @KennyTM.
 31 окт. 2017 г., 06:46
@ kirelagin Может быть, это и было задумано. В питонеrange(m, n) означает целочисленный интервал [m, n), то есть m, m + 1, m + 2, ..., n - 1. Он не включает n, поэтомуrange(-5, 257) не содержит 257, и описанное поведение верно для этого диапазона.
 13 июл. 2012 г., 20:34
Интересный перекос в положительную сторону. В статье говоритсяmany Python programs spend a lot of time using integers in that rangeпоэтому разработчики, вероятно, как-то это измерили. Я думаю, литералы отрицательных чисел используются только для кодов ошибок в эти дни ...

у него есть пул целочисленных объектов, из которых возвращаются эти целые числа. Вот почему эти объекты одинаковы:(0-5) а также-5 но нет(0-6) а также-6 так как они созданы на месте.

Вот источник в исходном коде CPython:

#define NSMALLPOSINTS           257
#define NSMALLNEGINTS           5
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

(просмотреть исходный код CPython: /trunk/Objects/intobject.c). Исходный код содержит следующий комментарий:

/* References to small integers are saved in this array so that they
   can be shared.
   The integers that are saved are those in the range
   -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/

is оператор потом их сравнит (-5) как равные, потому что это один и тот же объект (та же ячейка памяти), но два других новых целых числа (-6) будет в разных местах памяти (а затемis не вернетсяTrue). Обратите внимание, что257 в приведенном выше исходном коде для положительных целых чисел, так что0 - 256 (Включительно).

(источник)

Ваш ответ на вопрос