2017-01-26 2 views
2

Если я не ошибаюсь, a is b должен вернуть True, если a и b указывает на тот же объект. С двумя равными списками он возвращает False, потому что списки представляют собой два разных списка. Я думал, что неизменные объекты не имеют этой проблемы, но когда я ставлю в:Как интернирование работает с неизменяемыми объектами?

a = (1, 2, 3) 
b = (1, 2, 3) 
a is b #returns false 

Я подумал, что это должно вернуться True поскольку a и b точку неизменного объекта, который имеет такое же значение. Почему нет a, указывая на тот же объект, что и b, когда я использую кортежи?

+4

Не все неизменяемые объекты интернированы. –

+0

http://pythontutor.com/visualize.html#code=a%20%3D%20(1,%202,%203%29%0Ab%20%3D%20(1,%202,%203%29 % 0AA% 20is% 20b% 20% 23returns% 20false & кумулятивная = истина & curInstr = 3 & heapPrimitives = истина и режим отображения = & происхождение = неавтоматического интерфейс.js & py = 3 & rawInputLstJSON =% 5B% 5D & textReferences = false –

+1

Связано это: http://stackoverflow.com/q/6934202/4996248 –

ответ

4

Ваш a и b do не указывают на один и тот же объект (вы создаете два отдельных набора); вы можете проверить это с помощью id(a) или - как вы это сделали - с a is b.

a == b 

с другой стороны будет True.

Если вы хотите, чтобы они указывают на тот же объект, который вы могли бы сделать

a = b = (1, 2, 3) 

Теперь a is b является True.

Ничего из этого не связано с изменчивостью или неизменностью; он будет работать так же, если вы приняли list s вместо tuple s.

Вы можете визуализировать свой код pythontutor, чтобы узнать, что происходит.

Python делает несколько строк и некоторые небольшие целые числа (например, a=0; b=0; a is b дает True), но не все неизменяемые интернированы. Кроме того, вы не должны полагаться на это, скорее рассмотрите его как деталь реализации.

0

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

Interning предназначен исключительно для оптимизации использования памяти, и вы правы, что в принципе любой литерал неизменяемой ценности может быть интернирован, но это фактически выполняется только в самых тривиальных случаях.

Одна из вероятных причин того, что кортежи не интернированы, так это то, что они не являются глубоко неизменными. Если вы помещаете в них что-то изменчивое (например, ({}, [])), интернирование их может привести к неправильному поведению, так как изменение может изменить другое.

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

a = 1, 2, 3 
b = a 
Смежные вопросы