Список с тем же значением, а не с той же ссылкой - PullRequest
1 голос
/ 02 февраля 2020
>>> x = [(None, None), (None, None), (None, None)]
>>> y = [(None, None) for _ in range(3)]
>>> x[0] is x[1]
False
>>> y[0] is y[1]
True

Мне нужен список n значений (None, None), которые не являются ссылками на одно и то же значение.

Как мне заставить y вести себя как x, т. Е. Не ссылаться то же значение?

С этого поста Я ожидал, что y будет вести себя как x ...

Это использует Python 3.6

Ответы [ 3 ]

4 голосов
/ 02 февраля 2020

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

Причина, по которой y дает список из трех ссылок на один и тот же кортеж, заключается в том, что кортеж (None, None) является константой времени компиляции, поэтому его байт-код представляет собой простой LOAD_CONST, который выполняется внутри понимания списка и, конечно же, загрузка одной и той же константы три раза просто создает три ссылки на нее, а не три копии.

Чтобы обойти это, нам нужно выражение, значение которого равно (None, None), но для которого выражение не является константой времени компиляции. Вызов функции tuple делает это, по крайней мере в версиях Python, которые я тестировал (3.5.2 и 3.8.1):

[tuple([None, None]) for _ in range(3)]

Честно говоря, я немного удивлен, что x у него есть три разных копии, и это почти наверняка специфика реализации c, на которую вы не должны полагаться. Но, аналогично, tuple.__new__ не всегда создает новый кортеж; например tuple( (None, None) ) возвращает ссылку на фактический аргумент, а не его копию. Таким образом, не гарантируется, что tuple([None, None]) продолжит производить кортежи с неравными ссылками в других версиях Python.

3 голосов
/ 02 февраля 2020

Вы можете использовать функцию кортежа во временном списке:

>>> x = [(None, None), (None, None), (None, None)]
>>> y = [tuple([None, None]) for _ in range(3)]
>>> x[0] is x[1]
False
>>> y[0] is y[1]
False
0 голосов
/ 02 февраля 2020

y = [tuple([None, None]) for _ in range(3)] должно работать.

...