线性回归的从零开始实现

这里“外部对象是否会被改变,只取决于它是不是可变对象,和是否使用复合运算符无关”这个说法不太准确。

可以直接看同一个 list 的两个例子:

def f(x):
    x = x + [3]

x = [1, 2]
f(x)
print(x)
# [1, 2]

list 明明是可变对象,但外部的 x 并没有变化。原因是 x + [3] 创建了一个新的列表,函数里的局部变量 x 只是改为指向这个新列表,并没有修改原来的列表。

再看:

def f(x):
    x += [3]

x = [1, 2]
f(x)
print(x)
# [1, 2, 3]

这里外部的 x 就变了,因为对 list 来说,+= 会原地修改原来的列表。

另外:

def f(x):
    x[0] = x[0] + 1

x = [1, 2]
f(x)
print(x)
# [2, 2]

这里虽然右边 x[0] + 1 生成了一个新的整数,但左边 x[0] = ... 修改的是原列表内部的元素,所以外部仍然能看到变化。

所以更准确的说法应该是:

对象是否可变,决定它能不能被原地修改;而外部是否会看到变化,取决于函数内部这次操作到底是在原地修改原对象,还是只是让局部变量重新指向了一个新对象。

因此,“是否使用 +=-= 这类复合运算符”不能说完全无关。你原来的对比例子有一点问题:你比较的是对“列表元素”进行 += 和普通赋值,而不是直接对 list 对象本身进行比较。对于列表元素来说,两种写法最终都可能修改原列表中的那个位置,所以看起来差别不大。更合适的对比应该是直接比较:

x = x + [3]

和:

x += [3]

这样才能清楚体现“重新绑定局部变量”和“原地修改原对象”的区别。