Я обнаружил странное поведение с точкой с запятой ";" в Python.
>>> x=20000;y=20000
>>> x is y
True
>>> x=20000
>>> y=20000
>>> x is y
False
>>> x=20000;
>>> y=20000
>>> x is y
False
Почему первый тест возвращает «Истина», а остальные - «Ложь»? Моя версия Python - 3.6.5.
В интерактивном интерпретаторе первая строка с запятой считывается и оценивается за один проход. Таким образом, интерпретатор распознает, что 20000 - это одно и то же неизменное значение int
в каждом назначении, и поэтому жестяная банка (не обязательно, но делает) делает ссылки x
и y
на один и тот же объект.
Важным моментом является то, что это просто оптимизация, которую должен сделать интерактивный интерпретатор выбирает; это не что-то гарантированное языком или каким-то специальным свойством ;
, которое объединяет два оператора в один.
В следующих двух примерах к моменту считывания и оценки y=20000
x=20000
(с точкой с запятой или без нее) уже был оценен и забыт. Поскольку 20000 не находится в диапазоне (от -5 до 257) предварительно выделенных значений int
, CPython не пытается найти другой экземпляр 20000, уже находящийся в памяти; он просто создает новый для y
.
Не напрямую, но опять же, поскольку команды находятся в одном «пакете» ввода, у интерпретатора / компилятора есть больше возможностей для поиска оптимизаций. Кортеж, созданный с правой стороны, состоит из одного и того же литерала, повторяемого дважды, поэтому кортеж может быть создан с двумя ссылками на один и тот же объект, вместо того, чтобы выделять два отдельных объекта с одинаковым значением.
Также обратите внимание, что люди, создавшие интерпретатор мог, решили заставить интерпретатор повторно использовать объект 20000
для второго оператора; они просто этого не сделали. (И убедитесь, что вы понимаете разницу между is
и ==
- см. Ответ Роберто Бонвалле.)
Чтобы понять, что Почему 20000 не всегда повторно используется, рассмотрите разницу между тем, чтобы 20000 появлялись дважды в одном и том же выражении, которое вы обрабатываете в настоящее время, и попытками определить, оценивался ли литерал 20000 в какой-то произвольный момент в прошлом. Первый требует просто взглянуть на выражение, которое в настоящее время оценивается; последнее требует специальных структур данных в памяти для отслеживания живых объектов.
Оператор is
проверяет, являются ли два значения одним и тем же объектом в памяти. Он не предназначен для проверки на равенство. Для чего стоит, вы могли бы рассмотреть тот факт, что он иногда возвращает True
, а иногда и False
, просто на удачу (даже если это не так).
Например, результаты в интерактивном сеансе и в автономной программе разные:
$ cat test.py
x = 200000; y = 200000
print(x is y)
xx = 200000
yy = 200000
print(xx is yy)
$ python test.py
True
True
Или у вас есть другой пример:
>>> x = 50 + 50; y = 50 + 50
>>> x is y
True
>>> x = 5000 + 5000; y = 5000 + 5000
>>> x is y
False
Это происходит потому, что интерпретатор кэширует небольшие числа, поэтому они всегда являются одним и тем же объектом, но не для больших чисел, поэтому оба добавления во втором случае создают новый объект 10000
. Это не имеет ничего общего с точкой с запятой.
Почему можно считать это делом удачи, а это вовсе не так?
а когда вернет False?
@ IşıkKaplan Вы правы, что это не так. Я имею в виду, что на такое поведение нельзя положиться. В каком-то смысле это вопрос удачи, что интерпретатор выбирает оптимизацию, которая Чепнер упомянул, а также то, что пример был протестирован в интерактивной консоли (я попытался написать автономную программу, и результаты были другими).
@mad_ Я расширил свой ответ примером, в котором два выражения с одинаковым результатом, разделенные точкой с запятой, заставляют оператор is
возвращать False
.
Однако нет несоответствия, вы можете держаться подальше от неизменяемых встроенных модулей, чтобы не думать об оптимизации интерпретатора так много, но для пользовательских классов это всегда точно и то, на что можно положиться. Если не; Я хотел бы узнать, где он может вернуть неправильный результат в пользовательском классе.
Спасибо, я понял. Затем я также пробую
x,y=20000,20000
, "x is y" тоже возвращает истину. поэтому я думаю, что «x = 20000; y = 20000» можно оптимизировать до «x, y = 20000,20000».