Python作用域 可变 vs 不可变

6

首先,我和其他人一样,也是新手学习Python。我的老师给了我一个问题:

def f(a, b, c):  
    a    = 1 
    c    = b 
    c[0] = 2 
a = 10 
b = [11, 12, 13] 
c = [13, 14, 15] 
f(a, b, c) 
print a, b, c

它将打印如下内容:
10 [2, 12, 13] [13, 14, 15]

我理解为什么a保持在10,因为整数是不可变的,但我不明白为什么b会改变而c不会。


2
我还要指出,这与数据类型是可变还是不可变无关。如下面的答案所指出的,这与变量赋值有关。数据模型页面讨论了这种差异。 - Rob
让你感到困惑的只是变量名,我猜。给函数外部的变量不同的名称,比如x、y、z;这样你就可以调用f(x,y,z),并打印出x、y、z。我相信这不会太难看懂。 - Danny
3个回答

4
c    = b 
c[0] = 2

既然您将 c 设置为指向 b ,那么您也可以轻松地执行以下操作:

def f(a, b, unused): # notice c isn't in the parameter list  
    a = 1
    c = b # c is declared here
    c[0] = 2 # c points to b, so c[0] is b[0]

现在很明显,c 总是和 b 一样,那为什么不直接将其删除:
def f(a, b, unused):
    a = 1
    b[0] = 2

现在清楚的是,你正在改变b的第一个元素,并没有对c做任何操作。请记住,这与原始代码在功能上是相同的。


2
关键是要理解变量在内部是指针:
def f(a, b, c):  
    a    = 1 # a is a single scalar value, so no pointing involved
    c    = b # point the local "c" pointer to point to "b"
    c[0] = 2 # change the 2nd value in the list pointed to by "c" to 2

当你调用f(a,b,c)时,只有b实际上被改变了。函数实现内部的“c”变量与函数外部的“c”实现是不同的。


1

a 不保留值为10是因为它是不可变的。它保留值为10是因为当你在 f() 的本地作用域中调用 a = 1 时,你创建了一个新变量。

当你在 f() 中调用 c = b 时,本地的 c 成为对由 b 表示的可变对象的本地引用。当你重新分配该可变对象中的值时,更改会反映在原始对象中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接