2014-01-16 41 views
1

这可能看起来像一个非常愚蠢的问题,但我对Python中的作用域规则感到困惑。在下面的例子中,我将两个带有值的变量(x,y)发送给一个应该改变其值的函数。当我打印结果时,变量没有改变。如何更改函数中变量的范围? Python

def func1(x,y): 
    x=200 
    y=300 

x=2 
y=3 

func1(x,y) 

print x,y #prints 2,3 

现在,如果这是C++我想先引用(&),以该功能给他们,因此能够改变它们的值。那么Python中的equivilant是什么?更重要的是,当你发送对象到函数时实际发生了什么? Python是否会对这些对象进行新的引用?

+0

此外,[Python:如何通过引用传递变量?](http://stackoverflow.com/q/986006/395760)。 – delnan

+0

**全部** Python名称是对象的引用。函数参数仅与传入的对象绑定。您没有获得内存位置,在表达式中使用它时总是取消引用名称。作业正在重新绑定,而不是改变原始的存储位置。因此,'x = 200'正在创建一个新对象('int(200)'),并将该对象的引用存储在'x'中。 –

+0

内部作用域具有对来自外部作用域的*访问*变量的隐式权限,但需要显式权限才能修改来自外部作用域的变量。这简直就像我可以说的那样。 – roippi

回答

4

认为它们是功能的一部分。当函数结束时,它的所有变量也会死掉。

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 

为什么没有工作?那么因为你从来没有告诉程序去做任何事情,只需要计算它。现在我们来分配它

#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 
+0

如何使用函数更改x,y? –

+0

在函数末尾显式返回x,y,然后调用'x,y = func(x,y)' – jonrsharpe

+0

@ Reboot_87:你不能;你传入的对象是不可变的,因此不可能改变它们,并且你不能重新绑定外部作用域中的名称*只是基于传入的内容。(您可以使用'global'关键字在全局范围内重新命名'x'和'y',但不管传入什么对象,都会发生这种情况;在这种情况下,func(a,b)只会修改x和y。 .. – geoffspear