如果您在函数中分配变量名(未声明 global 或 nonlocal)或在函数的参数列表中使用变量名,则变量名将成为函数的一部分。
在这种情况下,你可以在函数中使用任何变量名,因为它总是引用传入的局部变量:
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,因为它现在是函数的一部分,您会得到一个明显的异常(因为即使@ 987654333@ 是未分配给它的函数的一部分尚未):
>>> 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 作为局部变量名的一部分,例如 global 或 @987654339 @:
def func():
global x # or "nonlocal x"
print(x)
x = 2
print(func.__code__.co_varnames)
# ()
当您调用 func() 时,这实际上会覆盖全局(或非局部)变量名称 x 所指的内容!