1.场景
有一天,同事问我:“我在动态改变一个list值的时候总是不遂人愿,你帮我看看是哪里出了问题?”
她的代码是这么写的:
#fromTongshi.py
#2020.06.07
language = ["Python",0]
scores = [75,80,90]
result = []
for score in scores:
language[-1] = score
result.append(language)
print(result)
她想象的结果是这样的:
[['Python', 75], ['Python', 80], ['Python', 90]]
而实际上结果是这样的:
[['Python', 90], ['Python', 90], ['Python', 90]]
问题出在哪里呢?
2.值和引用
在Python里,数据类型分为2种,可变类型和不可变类型。
可变类型:字典(dict), 集合(set), 列表(list)
不可变类型:整型(int), 字符串(string), 浮点型(float), 元组(tuple)
可变类型的对象在被调用时传递的是该对象的值。
不可变类型的对象在被调用时传递的是该对象的位于内存中的数据的引用。
来解释一下同事的难题:
language
是一个可变类型的对象。在result.append(language)
以后,language
将它的引用传递给了result
,
在第1次append
以后,result
有了1个language
的引用,此时result=[language的引用]
,而此时language
的引用指向的数据是['Python', 75]
。
在第2次append
以后,result
有了2个language
的引用,此时result=[language的引用, language的引用]
,而此时language
的引用指向的数据是['Python', 80]
。
在第3次append
以后,result
有了3个language
的引用,此时result=[language的引用, language的引用,language的引用]
,而此时language
的引用指向的数据是['Python', 90]
。
3.曲线救国
如果真的想实现这个功能应该怎么做呢?
我们可以利用一个中间变量,来保证每次循环时都重新生成这个变量。
如:
language = ["Python",0]
scores = [75,80,90]
result = []
for score in scores:
temp = language[:-1]
temp.append(score)
result.append(temp)
print(result)