在python中重新分配变量

Sus*_*sie 7 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)
Run Code Online (Sandbox Code Playgroud)

我尝试的解决方案如下:

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"]
Run Code Online (Sandbox Code Playgroud)

但实际的解决方案是:

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"]
Run Code Online (Sandbox Code Playgroud)

任何人都可以告诉我我的错误吗?

Pau*_*ine 7

好的,您可以将Python中的变量视为参考.当你这样做时:

a1 = a
Run Code Online (Sandbox Code Playgroud)

两者a1a是同一个对象的引用,因此,如果您通过修改所指向的对象a,你会看到变化a1,因为-惊喜-他们是同一个对象(和list.insert方法变异到位的列表).

但是当你这样做时:

a2 = a[:]
Run Code Online (Sandbox Code Playgroud)

然后a2是一个新list实例,当您修改时,a您不会修改a2.

+列表运算符的结果是一个新列表,因此当您执行以下操作时:

b = ['z'] + b
Run Code Online (Sandbox Code Playgroud)

您正在分配新列表,b而不是b像您一样在原地进行变更b.insert('z').现在b指向一个新对象,同时b1仍指向旧值b.

但是范围甚至可能更棘手:您可以从函数中看到封闭范围,但是如果在函数内部分配变量,它将不会更改封闭(或全局或内置)中具有相同名称的变量范围,它将在本地范围内创建一个具有此名称的变量.这就是为什么b没有被改变 - 好吧,不完全,Python中的参数传递是一个赋值操作,所以b当有一个名为的参数时已经是一个局部变量b- 但是试图改变在封闭范围内定义的变量会导致类似问题.顺便说一句,依赖来自封闭范围的变量是不好的做法,除非它们是模块级常量(传统上它们以ALL_UPPERCASE样式命名,你不应该改变它们).如果你需要函数内部的值,将它作为参数传递,并且你想要在封闭范围内更改变量的值,返回值并在那里分配返回的值:

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

b = do_something(a, b)
Run Code Online (Sandbox Code Playgroud)

  • 另外值得一提的是`do_something`中的`b`已在本地重新分配,因此不会改变全局`b`值. (2认同)
  • 在`do_something()`中计算的`b`的值是函数的局部值,并在该函数结束时被丢弃.函数不触及全局变量`b`,`b1`或`b2`. (2认同)