18
2016-11-21 16:18:09 +08:00 1
对象变动(Mutation)
Python 中可变(mutable)与不可变(immutable)的数据类型让新⼿很是头痛。 简单的说, 可
变(mutable)意味着"可以被改动", ⽽不可变(immutable)的意思是“常量(constant)”。 想把脑
筋转动起来吗? 考虑下这个例⼦:
foo = ['hi']
print(foo)
# Output: ['hi']
bar = foo
bar += ['bye']
print(foo)
# Output: ['hi', 'bye']
刚刚发⽣了什么? 我们预期的不是那样!我们期望看到是这样的:
foo = ['hi']
print(foo)
# Output: ['hi']
bar = foo
bar += ['bye']
print(foo)
# Output: ['hi']
print(bar)
# Output: ['hi', 'bye']
这不是⼀个 bug 。 这是对象可变性(mutability)在作怪。 每当你将⼀个变量赋值为另⼀个可
变类型的变量时, 对这个数据的任意改动会同时反映到这两个变量上去。 新变量只不过是
⽼变量的⼀个别名⽽已。 这个情况只是针对可变数据类型。 下⾯的函数和可变数据类型让
你⼀下就明⽩了:
def add_to(num, target=[]):
target.append(num)
return target
add_to(1)
# Output: [1]
add_to(2)
# Output: [1, 2]
add_to(3)
# Output: [1, 2, 3]
Python 进阶
对象变动 Mutation 51 你可能预期它表现的不是这样⼦。 你可能希望, 当你调⽤add_to 时, 有⼀个新的列表被
创建, 就像这样:
def add_to(num, target=[]):
target.append(num)
return target
add_to(1)
# Output: [1]
add_to(2)
# Output: [2]
add_to(3)
# Output: [3]
啊哈!这次又没有达到预期, 是列表的可变性在作怪。 在 Python 中当函数被定义时, 默认
参数只会运算⼀次, ⽽不是每次被调⽤时都会重新运算。 你应该永远不要定义可变类型的
默认参数, 除⾮你知道你正在做什么。 你应该像这样做:
def add_to(element, target=None):
if target is None:
target = []
target.append(element)
return target
现在每当你在调⽤这个函数不传⼊target 参数的时候, ⼀个新的列表会被创建。 举个例
⼦:
add_to(42)
# Output: [42]
add_to(42)
# Output: [42]
add_to(42)
# Output: [42]