在python中重新分配变量

Reassigning variables in python

本问题已经有最佳答案,请猛点这里访问。

我有以下代码和变量,我想找出代码执行后的变量aa1a2bb1b2

1
2
3
4
5
6
7
8
9
10
11
12
def do_something(a, b):
    a.insert(0,"z")
    b = ["z"] + b

a = ["a","b","c"]
a1 = a
a2 = a[:]
b = ["a","b","c"]
b1 = b
b2 = b[:]

do_something(a, b)

我尝试的解决方案如下:

1
2
3
4
5
6
a = ["z","a","b","c"]
a1 = ["a","b","c"]
a2 = ["a","b","c"]
b = ["z""a","b","c"]
b1 = ["a","b","c"]
b2 = ["a","b","c"]

但实际的解决方案是:

1
2
3
4
5
6
a = ["z","a","b","c"]
a1 = ["z","a","b","c"]
a2 = ["a","b","c"]
b = ["a","b","c"]
b1 = ["a","b","c"]
b2 = ["a","b","c"]

有人能带我度过我的错误吗?


好的,您可以将Python中的变量视为引用。当你这样做的时候:

1
a1 = a

a1a都是对同一对象的引用,因此,如果修改a指向的对象,您将看到a1中的更改,因为它们是同一对象(list.insert方法改变了列表的位置)。

但当你这样做的时候:

1
a2 = a[:]

那么,a2是一个新的list实例,修改a时,不修改a2

列表的+操作符的结果是一个新列表,因此当您这样做时:

1
b = ['z'] + b

您将为b分配一个新的列表,而不是像对b.insert('z')那样在适当位置对b进行变异。现在,b指向一个新的对象,而b1仍然指向b的旧值。

但是作用域可能更复杂:您可以从函数中看到封闭作用域,但是如果在函数中分配一个变量,它不会在封闭(或全局或内置)作用域中更改同名的变量,而是在本地作用域中创建一个同名的变量。这就是为什么b没有被改变的原因——好吧,不是很好,在python中传递参数是一个赋值操作,所以当有一个名为b的参数时,b已经是一个局部变量了——但是试图改变在封闭范围中定义的变量会导致类似的问题。顺便说一句,除非变量是模块级常量,否则依赖于封闭范围中的变量是不好的做法(传统上它们都是以大写形式命名的,并且您不应该改变它们)。如果需要函数内的值,请将其作为参数传递,如果要更改封闭范围内变量的值,请返回该值并在其中指定返回值:

1
2
3
4
5
def do_something(a, b):
    a.insert(0,"z")  # mutates a in-place
    return ["z"] + b

b = do_something(a, b)