Python 字典中的易变性

Python 字典中的易变性,python,mutability,Python,Mutability,为什么我的curr\u值没有从mydict变异?我没有克隆curr\u value或任何东西 >>> mydict = {1: {45: 'ades', 54:'adee'}, 2: {68: 'gdes'}} >>> curr_value = mydict[1][45] >>> mydict[1][45] = 'zzzz' >>> print (curr_value) ades # Expected value: zzz

为什么我的
curr\u值
没有从
mydict
变异?我没有克隆
curr\u value
或任何东西

>>> 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
输出:

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'}

这只是封装了您想要引用的dict中的点,函数在调用dict时获取dict的值。

无法创建一个普通变量,当其他数据结构更新时,该变量会自动“更新”。这种行为只能通过某种表达式实现,比如属性或项查找。换句话说,您可以创建一个对象
curr\u value
,这样计算
curr\u value[0]
时会得到
mydict[1][45]
的值,或者计算
curr\u value.value
时会得到
mydict[1][45]
的值,但是你不能这样做,只计算普通的
curr\u值
就可以得到此时的
mydict[1][45]
。执行
curr\u value=mydict[1][45]
始终将
curr\u值设置为您分配它时的值,并且如果
mydict[1][45]
发生更改,它将不会在以后更新。

您想要的是不可能的,因为简单的分配总是创建一个新的绑定(即,将新对象绑定到
=
符号LHS上的名称)。OTOH,执行变异不会创建新绑定,因此您可以这样做,例如

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)) 
根据需要打印
zzzz

在中,堆栈溢出专家Ned Batchelder很好地介绍了此主题,并在中进行了总结

另一个选择是这样做

ref = mydict[1]
mydict[1][45] = 'zzzz'
print(ref[45]) 
一般来说,最好避免造成这样的混乱,但有时这类事情是有用的。例如,通过向2D列表添加额外的间接层,我们可以通过列和行访问它

mydict = {1: {45: ['ades'], 54:['adee']}, 2: {68: ['gdes']}}
ref = mydict[1][45]
mydict[1][45][0]='zzzz'
print(ref[0]) 
输出

# 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)

在回答的开头,我说“简单赋值总是创建一个新的绑定”。但是,如果可能,将执行就地操作,即目标是一个可变对象。从文档:

x+=1
这样的增广赋值表达式可以重写为
x=x+1
以获得类似但不完全相同的效果 扩充版本,x只计算一次 实际操作在适当位置执行,这意味着 创建新对象并将其指定给目标,即旧对象 而是修改了


字符串是不可变的。
当前值
不包含引用,因为它是
字符串
对象,而不是
列表
。哦……有没有方法引用“ades”点?你为什么要问字典?
当前值
不引用字典对象,你可以简单地向自己演示f该字典已更改。它引用的字符串对象以前是,但现在不再是,也被
mydict[1]
字典引用,因此被
mydict
间接引用。您可能会发现这一点很有用:什么是“ades”点?您是指指针吗?您可以继续使用
mydict[1][45]
,这是您分配给的。分配给
curr\u value
也不会改变字典!您实际想要实现什么?
mydict[1][45]
始终引用ADE的点。如果您保持[1]和[45]处于活动状态,则在您的情况下…@user13123:使用'mydict[1][45]“如果值发生变化。这样你就可以得到当前存储的任何内容。不需要那种(注意!)语言,而且你刚刚制作了一个有限版本。谢谢你的尝试!但是你的概念对我来说太先进了:(@jornsharpe在查找后更正了这些胡说八道-我没有那么“苛刻”翻译存储,大致如下。如果我在他的dict上使用
f=itemgetter(1,45)
,我会得到一个itemerror-从docu中,它被用于1dim列表以获得倍数。是否存在一些“过载”对于这个用例?哦,对不起,我认为
itemgetter
是深入的,而不是从一个级别提取多个项目。谢谢。我现在明白了。
[[['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']]]