如何更改函数中变量的范围? Python [重复]

Posted

技术标签:

【中文标题】如何更改函数中变量的范围? Python [重复]【英文标题】:How to change the scope of a variable in a function? Python [duplicate] 【发布时间】:2014-02-05 19:00:03 【问题描述】:

这似乎是一个非常愚蠢的问题,但我对 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 是否对这些对象进行了新的引用?

【问题讨论】:

另外,Python: How do I pass a variable by reference?。 所有 Python 名称是对对象的引用。函数参数仅绑定到传入的对象。您没有获得内存位置,在表达式中使用它时总是取消引用该名称。赋值是重新绑定,而不是改变原来的内存位置。因此x = 200 正在创建一个新对象(int(200)),并将对该对象的引用存储在x 中。 内部作用域具有从外部作用域访问变量的隐式权限,但需要从外部作用域修改变量的显式权限。我可以说得非常简洁。 (CPython 可以选择在此处重用现有的int() 对象,但这是一个实现细节)。 因此,尽管 func1 内部的本地名称 xy 开始与模块范围内的全局 xy 名称绑定到相同的 int() 对象,通过在函数内部分配给它们,您只会反弹本地名称。全局名称仍然引用它们的原始值。 【参考方案1】:

将它们视为功能的一部分。当函数结束时,它的所有变量也都死掉了。

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

【讨论】:

如何使用函数改变 x,y? 在你的函数末尾显式return x, y然后调用x, y = func(x, y) @Reboot_87:你不能;您传入的对象是不可变的,因此无法更改它们,并且您无法根据传入的内容重新绑定外部范围内的名称just。(您可以使用global 关键字全局重新绑定名称 xy,但无论传入什么对象都会发生这种情况;在这种情况下 func(a, b) 只会修改 x 和 y... 我现在明白了。谢谢 @Reboot_87 我用不同的方法进行了相当大的编辑。试一试。如果您可以提供帮助,请不要使用global - 这是一种糟糕的做法,并且使调试变得非常困难。

以上是关于如何更改函数中变量的范围? Python [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Python嵌套函数变量范围[重复]

Python:如何允许“内部函数”更改多个“外部函数”中的非局部变量

在 Python 中更改函数的范围

为啥 Python 3.8.0 允许在不使用“非本地”变量的情况下从封闭函数范围更改可变类型?

JavaScript,当变量作为参数传递时更改函数内部的变量值[重复]

如何智能更改项目范围内的函数签名?