Python中的可变与不可变作用域

6 投票
3 回答
501 浏览
提问于 2025-04-17 07:50

首先,我和大家一样,刚开始接触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却没有。

3 个回答

1

a 不会保持10这个值是因为它是不可变的。它保持10这个值是因为当你在 f() 函数的局部范围内调用 a = 1 时,你实际上创建了一个新的变量。

当你在 f() 函数内调用 c = b 时,局部的 c 变成了一个指向 b 所代表的可变对象的引用。当你在这个可变对象中重新赋值时,变化会反映到原来的对象上。

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" 变量是不同的。

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 做任何事情,记住,这和最开始的效果是一样的。

撰写回答