python - 为什么可以在主范围中声明的函数中使用变量而不是全局变量

时间:2016-04-09 01:31:59

标签: python global-variables

我最近发现了一些我不希望使用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没有定义?
  3. 我知道我们可以使用global来完成这项工作,因为我们明确地说在我们想要访问的函数范围之外有一个变量,所以它会有意义。

    我发现这很棘手,因为它可能会导致错误。

3 个答案:

答案 0 :(得分:1)

myvar处于全局范围内,因此无论您是否声明它都是全局的。读取时,python查看函数的本地作用域,然后回退到定义变量的模块全局作用域。写的时候,python有问题。它应该在本地函数范围还是全局范围内分配变量? global关键字在函数中使用,并告诉该函数如何解决该问题。该变量从未被声明为全局变量,该函数被告知将该变量视为全局变量。

def my_func(mval):
    global myval
    myval = 'foo'  # set in global scope
    myval2 = 'bar' # set in local scope

答案 1 :(得分:1)

当您使用您提供的确切代码作为参考显示myvarmy_func的内容时,它将检查全局变量表以查看它是否先前在执行中定义,这就是为什么有用。然后,当您尝试通过取消注释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

答案 2 :(得分:0)

定义函数时,仅针对语法评估其正确性,因此不会引发任何内容。一旦调用函数myvar已在全局范围内定义,因此该函数有效。此外,如果您取消注释myvar = 'value' my_func,只要在调用函数之前定义myvar,也会毫无例外地进行评估。