这似乎是一个非常愚蠢的问题,但我对 Python 中的范围规则感到困惑。在下面的示例中,我将两个带有值的变量 (x,y) 发送给一个函数,该函数应该更改它们的值。当我打印结果时,变量没有改变。
def func1(x,y):
x=200
y=300
x=2
y=3
func1(x,y)
print x,y #prints 2,3
现在,如果这是 C++,我会通过引用 (&) 将它们发送给该函数,因此能够更改它们的值。那么 Python 中的等价物是什么?更重要的是,当您将对象发送给函数时实际发生了什么? Python 是否对这些对象进行新引用?
将它们视为函数的一部分。当函数结束时,它的所有变量也会消失。
x=2
y=3
def func(x,y):
x=200
y=300
func(x,y) #inside this function, x=200 and y=300
#but by this line the function is over and those new values are discarded
print(x,y) #so this is looking at the outer scope again
如果您希望函数按照您编写的方式修改值,您可以使用 global
,但这是非常糟糕的做法。
def func(x,y):
global x #these tell the function to look at the outer scope
global y #and use those references to x and y, not the inner scope
x=200
y=300
func(x,y)
print(x,y) #prints 200 300
这样做的问题是,它使调试在最好的情况下成为一场噩梦,而在最坏的情况下则完全无法理解。像这样的事情在函数中通常被称为“副作用”——设置一个你不需要设置的值并且在没有明确返回它的情况下这样做是一件坏事。通常,您应该编写的就地修改项目的唯一函数是对象方法(像 [].append()
修改列表,因为返回一个新列表是愚蠢的!)
做这样的事情的正确方法是使用返回值。尝试类似的东西
def func(x,y):
x = x+200 #this can be written x += 200
y = y+300 #as above: y += 300
return (x,y) #returns a tuple (x,y)
x = 2
y = 3
func(x,y) # returns (202, 303)
print(x,y) #prints 2 3
为什么那行不通?好吧,因为您从未告诉程序对该元组 (202, 303)
执行任何操作,只是为了计算它。让我们现在分配它
#func as defined above
x=2 ; y=3
x,y = func(x,y) #this unpacks the tuple (202,303) into two values and x and y
print(x,y) #prints 202 303