在Python中重新分配变量

7 浏览
0 Comments

在Python中重新分配变量

我有以下的代码和变量,并且我想知道代码执行后变量a、a1、a2、b、b1和b2指向的内容是什么。

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)

我的尝试解答如下:

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"]

但实际解答是:

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"]

有人能指出我哪里出错了吗?

0
0 Comments

在Python中,变量可以被看作是引用。当执行以下操作时:

a1 = a

`a1`和`a`都是指向同一个对象的引用,所以如果你修改`a`指向的对象,你会在`a1`中看到这些变化,因为它们实际上是同一个对象(`list.insert`方法会直接在原地修改列表)。

但是当执行以下操作时:

a2 = a[:]

`a2`是一个新的`list`实例,当你修改`a`时,不会影响到`a2`。

使用`+`运算符连接两个列表时,会创建一个新的列表,所以当执行以下操作时:

b = ['z'] + b

实际上是将一个新的列表赋值给了`b`,而不是像使用`b.insert('z')`一样在原地修改`b`。现在,`b`指向了一个新的对象,而`b1`仍然指向旧的`b`的值。

但是作用域可能变得更加棘手:你可以从函数中访问封闭的作用域,但是如果在函数内部赋值给一个变量,它不会改变封闭作用域(或者全局作用域、内置作用域)中同名的变量,而是在本地作用域中创建一个变量。这就是为什么`b`没有被改变的原因 - 可以说不完全准确,因为Python中的参数传递是一个赋值操作,所以当有一个名为`b`的参数时,`b`已经是一个局部变量了 - 但是尝试修改封闭作用域中定义的变量会导致类似的问题。

顺便说一下,依赖封闭作用域中的变量是不好的实践,除非它们是模块级常量(传统上它们以全大写的方式命名,你不应该对它们进行修改)。如果你需要在函数内部使用某个变量的值,请将其作为参数传递进去,如果你想在封闭作用域中更改变量的值,请返回该值并在那里进行赋值:

def do_something(a, b):
    a.insert(0, "z")  # 在原地修改a
    return ["z"] + b
b = do_something(a, b)

还值得一提的是,在`do_something()`中的`b`已经在本地重新赋值了,所以它不会改变全局的`b`值。在`do_something()`中计算的`b`的值是局部的,当函数结束时会丢弃掉。全局变量`b`、`b1`和`b2`都不会受到这个函数的影响。

0