LEGB规则是Python中命名空间(作用域)查找的规则。缩写代表着:
len,list等)。当Python遇到一个变量时,它首先在局部查找,然后在嵌套函数中查找,接下来在模块的全局范围内查找,最后在内置对象的命名空间中查找:
def outer(): x = 'enclosing' def inner(): x = 'local' print(x) inner() outer() # 'local'
如果在inner()内部去掉对x的赋值,Python会从外部作用域(outer)中获取x。如果那里也没有变量,就会查找全局变量,然后是内置的。
如果在修改外层作用域的变量时忘记声明
nonlocal或global,函数的行为会有什么变化?
回答:
如果试图在嵌套函数内修改外层作用域的变量而没有声明nonlocal(或global — 如果变量是在模块中),Python会创建一个新的局部变量,而不会修改外部变量。
示例:
x = 10 def foo(): x = 20 # 这是一个新的局部x,全球x没有改变 foo() print(x) # 10
要修改全局x:
def foo(): global x x = 20
对于外部函数的变量 — 使用nonlocal。
故事1
在一个教育项目中,使用嵌套函数计算调用次数。开发者写道:
def counter(): count = 0 def inc(): count += 1 return count return inc
但出现了UnboundLocalError,因为在inc()内的count被认为是新的(创建了局部count)。解决方案:声明count为nonlocal。
故事2
在web应用中,希望在处理程序内全局修改指定的缓存:
cache = {} def add_to_cache(key, value): cache[key] = value
然而如果在函数内部试图完全重写cache,例如cache = {key: value},这将创建一个新的局部cache,与全局cache没有关联,因为缺少global cache。
故事3
在一个大型ETL系统中发现了一个错误:程序员在函数内部没有明确初始化变量result,期待它会从外部作用域获取。但经过几次迭代后结果开始出错,因为内部是result += value,而不是result = result + value(没有nonlocal/global)— result在每次调用时都会重新初始化。