【发布时间】:2013-02-25 00:22:22
【问题描述】:
dic = {'a':'1','b':'2'}
lis = ['a','b']
for c in lis:
c = dic[c]
print lis
列表没有改变。我曾预计该列表将更改为['1','2']。谁能解释一下?
【问题讨论】:
标签: python list dictionary replace
dic = {'a':'1','b':'2'}
lis = ['a','b']
for c in lis:
c = dic[c]
print lis
列表没有改变。我曾预计该列表将更改为['1','2']。谁能解释一下?
【问题讨论】:
标签: python list dictionary replace
不,这不是列表迭代的工作方式。 c 在每次迭代时都是一个新对象,如果您更改该对象,原始列表(谢天谢地!)不会被修改。
如果您确实需要,请使用enumerate():
dic = {'a':'1','b':'2'}
lis = ['a','b']
for i, c in enumerate(lis):
lis[i] = dic[c]
print lis
【讨论】:
您在迭代中缺少的最重要的事情是,将元素分配给名称 c、c=dic[c] 会将 c 重新绑定到新对象,并且不会更新原对象。考虑以下演示
>>> for i, c in enumerate(lst):
print id(c), id(lst[i]),
c=dic[c]
print id(c)
4935168 4935168 4934712
4935192 4935192 5496728
因此,尽管在分配之前,列表元素和c 都引用了列表中的同一个对象,但分配字典的值只会更改引用
注意,这里id只是指引用对象的标识符
注意,当您更改整个列表时,使用 List Comprehension 会更轻松、更快捷
lst = [dic[e] for e in lst]
['1', '2']
警告不要将变量命名为内置变量
【讨论】:
尝试使用索引而不是变量...
for i in range(len(li)):
c = li[i]
li[i] = dic[c]
print li
另外,永远不要使用list 作为变量名..
或使用enumerate 喜欢
for i, c in enumerate(li):
li[i] = dic[c]
print li
或列表推导
lis = [dic[c] if c in dic else c for c in lis]
为什么不这样做?
当你使用for x in y:时,x获取y中的对象/项的值
因此,如果您更改x 的值,您不会更改y[i] 的值,i 是您所在的索引。
所以,如果你这样做
>>> y = range(5,10)
>>> for x in y:
i = y.index(x)
x += 10
print i
print 'Value of x : %3d, id: %7d' % (x, id(x))
print 'Value of y[i] : %3d, id: %7d' % (y[i], id(y[i]))
print '-'*31
你会看到区别
【讨论】:
当你这样做时
for c in myList:
c = something
您正在将名称 c 重新绑定到任何“某物”,在本例中为 dic[c] 的值。为了让 Python 真正“进入”列表,您必须调用该列表上的一个方法——list.__setitem__() 方法告诉 Python 访问实际的列表对象并 mutate 中的一个项目那个列表,不做简单的变量赋值。
for i, c in enumerate(myList):
myList.__setitem__(dic[c])
当然,这也可以写成(更pythonic):
for i, c in enumerate(myList):
myList[i] = dic[c]
看起来像变量赋值,其实不是。
【讨论】: