为什么可以在主作用域中声明而不是全局的函数中使用变量



我最近注意到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
  1. 为什么my_func可以访问myvar?然后它为什么会失败试图改变价值
  2. 有没有办法防止这种行为,那么在这种情况下,它会说变量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',只要在调用函数之前定义了myvarmy_func也将毫无例外地进行计算。

相关内容

  • 没有找到相关文章