我有以下的代码和变量,我想找到什么样的变量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)
任何人都可以告诉我我的错误吗?
好的,您可以将Python中的变量视为参考.当你这样做时:
a1 = a
Run Code Online (Sandbox Code Playgroud)
两者a1并a是同一个对象的引用,因此,如果您通过修改所指向的对象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)