Почему добавление точки с запятой в python меняет результат?

Я обнаружил странное поведение с точкой с запятой ";" в 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.

16
0
810
2

Ответы 2

В интерактивном интерпретаторе первая строка с запятой считывается и оценивается за один проход. Таким образом, интерпретатор распознает, что 20000 - это одно и то же неизменное значение int в каждом назначении, и поэтому жестяная банка (не обязательно, но делает) делает ссылки x и y на один и тот же объект.

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

В следующих двух примерах к моменту считывания и оценки y=20000x=20000 (с точкой с запятой или без нее) уже был оценен и забыт. Поскольку 20000 не находится в диапазоне (от -5 до 257) предварительно выделенных значений int, CPython не пытается найти другой экземпляр 20000, уже находящийся в памяти; он просто создает новый для y.

Спасибо, я понял. Затем я также пробую x,y=20000,20000, "x is y" тоже возвращает истину. поэтому я думаю, что «x = 20000; y = 20000» можно оптимизировать до «x, y = 20000,20000».

longshuai ma 13.09.2018 20:26

Не напрямую, но опять же, поскольку команды находятся в одном «пакете» ввода, у интерпретатора / компилятора есть больше возможностей для поиска оптимизаций. Кортеж, созданный с правой стороны, состоит из одного и того же литерала, повторяемого дважды, поэтому кортеж может быть создан с двумя ссылками на один и тот же объект, вместо того, чтобы выделять два отдельных объекта с одинаковым значением.

chepner 13.09.2018 20:45

Также обратите внимание, что люди, создавшие интерпретатор мог, решили заставить интерпретатор повторно использовать объект 20000 для второго оператора; они просто этого не сделали. (И убедитесь, что вы понимаете разницу между is и == - см. Ответ Роберто Бонвалле.)

Aasmund Eldhuset 13.09.2018 21:34

Чтобы понять, что Почему 20000 не всегда повторно используется, рассмотрите разницу между тем, чтобы 20000 появлялись дважды в одном и том же выражении, которое вы обрабатываете в настоящее время, и попытками определить, оценивался ли литерал 20000 в какой-то произвольный момент в прошлом. Первый требует просто взглянуть на выражение, которое в настоящее время оценивается; последнее требует специальных структур данных в памяти для отслеживания живых объектов.

chepner 13.09.2018 21:43

Оператор 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. Это не имеет ничего общего с точкой с запятой.

Почему можно считать это делом удачи, а это вовсе не так?

Işık Kaplan 13.09.2018 20:22

а когда вернет False?

mad_ 13.09.2018 20:26

@ IşıkKaplan Вы правы, что это не так. Я имею в виду, что на такое поведение нельзя положиться. В каком-то смысле это вопрос удачи, что интерпретатор выбирает оптимизацию, которая Чепнер упомянул, а также то, что пример был протестирован в интерактивной консоли (я попытался написать автономную программу, и результаты были другими).

Roberto Bonvallet 13.09.2018 20:35

@mad_ Я расширил свой ответ примером, в котором два выражения с одинаковым результатом, разделенные точкой с запятой, заставляют оператор is возвращать False.

Roberto Bonvallet 13.09.2018 20:43

Однако нет несоответствия, вы можете держаться подальше от неизменяемых встроенных модулей, чтобы не думать об оптимизации интерпретатора так много, но для пользовательских классов это всегда точно и то, на что можно положиться. Если не; Я хотел бы узнать, где он может вернуть неправильный результат в пользовательском классе.

Işık Kaplan 13.09.2018 20:46

Другие вопросы по теме