我最近注意到python中没有预料到的事情,可以检查/访问在主作用域中声明的函数中的变量,例如:
def my_func(mval):
print ("parameter:", mval)
print ("myvar:", myvar)
#myvar = "value" this is not allowed
print ("IN MAIN")
myvar = "123"
my_func(999)
输出:
IN MAIN
parameter: 999
myvar: 123
- 为什么
my_func
可以访问myvar
?然后它为什么会失败试图改变价值 - 有没有办法防止这种行为,那么在这种情况下,它会说变量
myvar
没有定义
我知道我们可以使用global
来实现这一点,这是有意义的,因为我们明确地说,在我们想要访问的函数范围之外有一个变量。
我觉得这很棘手,因为它可能会导致错误。。
myvar
在全局范围内,因此无论您是否声明它,它都是全局的。读取时,python在函数的本地作用域中查找,然后返回到定义变量的模块全局作用域。编写时,python有一个问题。它应该在局部函数作用域还是全局作用域中分配变量?在函数中使用global
关键字,并告诉该函数如何解决该问题。该变量从未被声明为全局变量,函数被告知将该变量视为全局变量。
def my_func(mval):
global myval
myval = 'foo' # set in global scope
myval2 = 'bar' # set in local scope
当您在my_func
中显示myvar
的内容,并将您提供的确切代码作为参考时,它将检查全局变量表,看看它是否在执行中以前定义过,这就是它工作的原因。然后,当您试图通过取消对myvar = "value"
的注释来在函数中为其赋值时,它会尝试将myvar
定义为my_func
的局部变量,从而隐藏对myvar
全局实例的引用。
我不确定使用global
关键字会导致什么问题,但它应该按预期工作。以下是如何使用它的示例:
def my_func(mval):
global myvar
print ("parameter:", mval)
print ("myvar:", myvar)
myvar = "value"
print ("IN MAIN")
myvar = "123"
my_func(999)
print("myvar after my_func:", myvar)
输出:
IN MAIN
parameter: 999
myvar: 123
myvar after my_func: value
如果你真的不想使用global
关键字,你可以通过传递myvar
作为my_func
的参数来实现所需的行为,并返回修改后的值以在主作用域中重新分配它:
def my_func(mval, myvar):
print ("parameter:", mval)
print ("myvar:", myvar)
myvar = "value"
return myvar
print ("IN MAIN")
myvar = "123"
myvar = my_func(999, myvar)
print ("myvar after my_func:", myvar)
输出:
IN MAIN
parameter: 999
myvar: 123
myvar after my_func: value
如果my_func
已经构建为返回一个值,请记住,您可以在Python中返回多个值。因此,假设my_func
将返回一个名为returnvar
的变量,则上述代码可以写成:
def my_func(mval, myvar):
returnvar = mval + 1
print ("parameter:", mval)
print ("myvar:", myvar)
myvar = "value"
return myvar, returnvar
print ("IN MAIN")
myvar = "123"
myvar, returnvar = my_func(999, myvar)
print ("myvar after my_func:", myvar)
print ("returnvar:", returnvar)
输出:
IN MAIN
parameter: 999
myvar: 123
myvar after my_func: value
returnvar: 1000
当您定义函数时,它不是仅针对语法进行正确性评估,因此不会引发任何问题。调用函数后,myvar
已在全局范围中定义,因此该函数是有效的。此外,如果取消注释myvar = 'value'
,只要在调用函数之前定义了myvar
,my_func
也将毫无例外地进行计算。