Изменчивость в словаре
>>> mydict = {1: {45: 'ades', 54:'adee'}, 2: {68: 'gdes'}}
>>> curr_value = mydict[1][45]
>>> mydict[1][45] = 'zzzz'
>>> print (curr_value)
ades # Expected value: zzzz
Как же мой curr_value
не мутирует от mydict
? Я не клонировал curr_value
или что-нибудь.
3 ответа
Нет способа создать простую переменную, которая "обновляет" себя, когда обновляется какая-то другая структура данных. Такое поведение может быть достигнуто только с помощью таких выражений, как поиск атрибутов или элементов. Другими словами, вы можете сделать объект curr_value
так что оценивая curr_value[0]
дает вам значение mydict[1][45]
в тот момент, или оценивая curr_value.value
дает вам значение mydict[1][45]
в этот момент, но вы не можете сделать так, чтобы оценка просто curr_value
дает вам значение mydict[1][45]
в тот момент. дела curr_value = mydict[1][45]
всегда устанавливает curr_value
к тому, что это в данный момент, вы назначаете его, и он не будет обновляться позже, если mydict[1][45]
изменения.
mydict = {1: {45: 'ades', 54:'adee'}, 2: {68: 'gdes'}}
curr_value = mydict[1][45]
mydict[1][45] = 'zzzz'
print (curr_value)
print(mydict)
Выход:
ades
{1: {45: 'zzzz', 54: 'adee'}, 2: {68: 'gdes'}
Ваш словарь изменчив - он был видоизменен. curr_value
является строкой и не является изменяемой
Средне раздражающая идея:
def boll(tpl):
return mydict[tpl[0]][tpl[1]]
mydict = {1: {45: 'ades', 54:'adee'}, 2: {68: 'gdes'}}
curr_value = (1,45)
print (boll(curr_value))
mydict[1][45] = 'zzzz'
print (boll(curr_value))
Это просто заключает в себе запоминание точки внутри dict, на которую вы хотите сослаться, и функция возвращает вам значение dict в тот момент, когда вы его называете.
То, что вы хотите, не возможно, потому что простое назначение всегда создает новую привязку (т. Е. Привязывает новый объект к имени на LHS =
знак). OTOH, выполнение мутации не создает новую привязку, так что вы можете сделать, например,
ref = mydict[1]
mydict[1][45] = 'zzzz'
print(ref[45])
который печатает zzzz
по желанию.
Эта тема хорошо освещена ветераном Stack Overflow Недом Батчелдером в " Фактах и мифах об именах и значениях Python", а в " Других языках" есть "переменные", в Python "имена".
Другой вариант сделать
mydict = {1: {45: ['ades'], 54:['adee']}, 2: {68: ['gdes']}}
ref = mydict[1][45]
mydict[1][45][0]='zzzz'
print(ref[0])
Обычно лучше избегать подобных помех, но иногда такие вещи полезны. Например, добавив дополнительный слой косвенности в 2D-список, мы можем сделать его доступным через столбцы, а также через строки.
# Create the grid
rows = [[[u+v] for u in 'abcd'] for v in 'wxyz']
cols = [list(u) for u in zip(*rows)]
print(rows)
print(cols)
print()
# Mutate some grid cells
cell = rows[1][2]
cell[0] = cell[0].upper()
cell = cols[0][3]
cell[0] = cell[0].upper()
print(rows)
print(cols)
выход
[[['aw'], ['bw'], ['cw'], ['dw']], [['ax'], ['bx'], ['cx'], ['dx']], [['ay'], ['by'], ['cy'], ['dy']], [['az'], ['bz'], ['cz'], ['dz']]]
[[['aw'], ['ax'], ['ay'], ['az']], [['bw'], ['bx'], ['by'], ['bz']], [['cw'], ['cx'], ['cy'], ['cz']], [['dw'], ['dx'], ['dy'], ['dz']]]
[[['aw'], ['bw'], ['cw'], ['dw']], [['ax'], ['bx'], ['CX'], ['dx']], [['ay'], ['by'], ['cy'], ['dy']], [['AZ'], ['bz'], ['cz'], ['dz']]]
[[['aw'], ['ax'], ['ay'], ['AZ']], [['bw'], ['bx'], ['by'], ['bz']], [['cw'], ['CX'], ['cy'], ['cz']], [['dw'], ['dx'], ['dy'], ['dz']]]
В начале этого ответа я заявил, что "простое назначение всегда создает новую привязку". Однако расширенное присваивание будет выполнять операцию на месте, когда это возможно, то есть цель является изменяемым объектом. Из документов:
Расширенное выражение присваивания, как
x += 1
может быть переписан какx = x + 1
добиться аналогичного, но не совсем равного эффекта. В расширенной версии x оценивается только один раз. Кроме того, когда это возможно, фактическая операция выполняется на месте, что означает, что вместо создания нового объекта и назначения его цели, старый объект вместо этого изменяется.