可变性指的是是否可以在不改变其标识符(内存地址)的情况下修改对象:
对函数的影响:
示例:
def f(lst): lst.append(42) data = [] f(data) print(data) # [42] def f2(x): x += 1 n = 1 f2(n) print(n) # 1
"以下代码将输出什么?"
def foo(bar=[]): bar.append(1) return bar print(foo()) print(foo())
答案: 将输出:
[1]
[1, 1]
因为函数参数在定义时只被初始化一次,而不是每次调用时。列表(和其他可变对象)作为函数参数——是一个常见的陷阱。
故事
在REST API中,通过带有默认参数的函数返回列表:
def get_default_items(items=[]): items.append('x') return items
经过几次调用发现,列表不断增长,而只希望获得一个元素。
故事
在函数中计划"替换"字符串:
def replace_word(word): word.replace('a', 'b') word = 'data' replace_word(word) print(word) # 希望得到'dbtb', 实际得到'data'
str方法不修改原始字符串,而是返回一个新字符串,但忽略了返回值。
故事
在处理嵌套结构时:
original = [[1, 2], [3, 4]] copy = original[:] copy[0][0] = -1 print(original) # [[-1, 2], [3, 4]]
使用了浅拷贝,以为只改变了副本,但嵌套对象仍然是共享的。