在这种情况下,全局变量和局部变量如何表现?

时间:2017-08-29 13:21:30

标签: python function global-variables variable-names

这保存在我的文件function_local.py中:

x = 50

def func(x):
    print('x is', x)
    x = 2
    print('Changed local x to', x)

func(x)
print('x is still', x)

输出:

$ python function_local.py
x is 50
Changed local x to 2
x is still 50

问题:当我们在函数内打印第一行时,为什么打印出50而不是2?即使在函数中说x = 2

3 个答案:

答案 0 :(得分:3)

如果您在函数中分配变量名称(未声明globalnonlocal)或在函数的参数列表中使用变量名称,变量名称将成为功能的一部分。

在这种情况下,你可以在函数中使用任何变量名,因为它总是引用传入的局部变量:

x = 50

def func(another_x):
    print('local x =', another_x)
    another_x = 2
    print('local x =', another_x)
    return another_x

print('global x =', x)
x = func(x)                # note that I assigned the returned value to "x" to make the change visible outside
print('global x =', x)

更多解释

当我说x与"将成为该功能的一部分时,我将尝试展示我的意思。

函数的__code__.co_varnames包含函数的局部变量名称列表。因此,让我们看看在少数情况下会发生什么:

如果它是签名的一部分:

def func(x):    # the name "x" is part of the argument list
    pass

print(func.__code__.co_varnames)
# ('x',)

如果指定给变量(函数中的任何位置):

def func():
    x = 2    # assignment to name "x" inside the function

print(func.__code__.co_varnames)
# ('x',)

如果您访问变量名称:

def func():
    print(x)

print(func.__code__.co_varnames)
# ()

在这种情况下,它实际上会在外部作用域中查找变量名称,因为变量名x不是函数varnames的一部分!

我可以理解这会让你感到困惑,因为只需在函数中的任何地方添加x=<whatever>就可以使它成为函数的一部分:

def func():
    print(x)  # access
    x = 2     # assignment

print(func.__code__.co_varnames)
# ('x',)

在这种情况下,赢了从外部范围查找变量x,因为它现在是函数的一部分而且你会得到告诫异常(因为即使x是函数的一部分,它也没有分配给但是):

>>> func()
UnboundLocalError: local variable 'x' referenced before assignment

显然,如果你在分配它后访问它会有效:

def func():
    x = 2     # assignment
    print(x)  # access

或者如果你在调用函数时传递它:

def func(x):  # x will be passed in
    print(x)  # access

关于局部变量名的另一个要点是你不能从外部作用域设置变量,除非你告诉Python明确地不使x成为局部变量名的一部分,例如使用{{ 1}}或global

nonlocal

这实际上会覆盖调用def func(): global x # or "nonlocal x" print(x) x = 2 print(func.__code__.co_varnames) # () 时全局(或非本地)变量名x所指的内容!

答案 1 :(得分:0)

在你的功能中

def func(x):
 print('x is', x)
 x = 2
 print('Changed local x to', x)

x不是全局变量;它是一个局部变量,因为在身体的第二行上赋值。如果要分配给全局变量,则必须将其显式声明为:

def func(x):
 global x
 print('x is', x)
 x = 2
 print('Changed local x to', x)

(注意:我错过了x实际上是一个函数参数。有关本地名称赋值的说明不会影响全局名称,请参阅https://nedbatchelder.com/text/names.html。)

答案 2 :(得分:0)

这可以很容易理解。

x = 50

def func(x):
    print "Local variables: "+str(locals())
    print('x is', x)
    x = 2
    print "Local variables: "+str(locals())
    print('Changed local x to', x)

func(x)
print('x is still', x)

和输出

Local variables: {'x': 50}
'x is', 50
Local variables: {'x': 2}
'Changed local x to', 2
'x is still', 50

但是,如果要在x中定义x之后想要从外部范围访问func有一种方法,我不确定它是否会产生问题但是。

def func(x):
    x = 2
    print "local x == %s" % x
    print "global x == %s" % globals().get('x')

func(x)
print "x is still %s" % x 

以下将输出运行。

local x == 2
global x == 50
x is still 50