本文共 2573 字,大约阅读时间需要 8 分钟。
在编程中,变量的作用域是理解代码行为的关键概念。一个变量可以属于局部作用域或全局作用域。定义在函数内的变量具有局部作用域,而在模块最高级别定义的变量则属于全局作用域。
全局变量的特点是除非被显式删除,否则它们会一直存在到脚本运行结束,并且可以在所有函数中访问。相比之下,局部变量的生命周期仅取决于其定义函数的执行阶段。
在Python中,变量查找遵循局部-外部-全局-内建(LEGB)的顺序优先级。在局部作用域未找到变量时,才会在外部作用域、全局作用域和内建作用域中依次查找。如果仍未找到,则会抛出NameError异常。因此,局部变量可以“隐藏”或覆盖全局变量。
由于闭包和嵌套函数的引入,作用域的层次变得更复杂。变量查找的优先级顺序变为:局部、外部、全局和内建。需要注意的是,只有def、class和lambda等语句会产生新的作用域,而if、try、for等语句不会创建新的作用域。
例如,在以下函数中,变量a仍然属于局部作用域,而不是由if语句引入的新作用域:
def foo(): if True: a = 2 print(a)
a可以在print语句中访问,因为它属于局部作用域。
在函数内部对全局变量进行赋值时,必须使用global声明,否则会导致UnboundLocalError异常。例如:
>>> gv = 4>>> def bar():... gv += 2... Traceback (most recent call last): File "", line 1, in File " ", line 2, in barUnboundLocalError: local variable 'gv' referenced before assignment
此外,局部变量可以覆盖全局变量,需要谨慎处理。例如:
>>> def foo():... lv = 2... gv = 3... print('lv is %d, gv is %d' % (lv, gv))... >>> gv = 4>>> foo()lv is 2, gv is 3 在函数内部明确使用全局变量时,必须使用global声明。
在Python2.1之前的版本中,函数嵌套会导致作用域扩展问题。例如:
def foo(): m = 3 def bar(): n = 4 print(m + n) print(m) bar()
在Python2.1之前运行会导致错误,但在现代Python版本中可以正常运行。
Python的lambda匿名函数遵循与标准函数相同的作用域规则。一个lambda表达式定义了一个新的作用域,该作用域中的变量不能在程序其他部分访问。
闭包(Closure)是指在内部函数中引用外部作用域变量的函数。闭包通过引用外部作用域的变量实现,其行为类似于记忆化。闭包的环境包括外部函数中的变量和上下文。
例如:
def line_conf(): b = 15 def line(x): return 2 * x + b return linemy_line = line_conf()print(my_line(5)) # 输出 25
line函数引用了line_conf作用域中的变量b,因此my_line携带了b的值。
闭包的一个重要特性是它会携带其创建时所依赖的环境变量。即使外部函数退出,闭包仍然保留环境变量的引用。
例如:
def counter(start_at=0): count = [start_at] def incr(): count[0] += 1 return count[0] return incrcount = counter(5)print(count()) # 输出 6print(count()) # 输出 7count2 = counter(100)print(count2()) # 输出 101print(count()) # 输出 8
闭包会携带外部函数的环境变量。
需要注意的是,闭包不能直接修改外部变量,除非使用nonlocal关键字(Python3引入)。例如:
def counter2(start_at=0): count = start_at def incr(): count += 1 return count return incrcount = counter2(5)print(count()) # 会抛出UnboundLocalError
此外,闭包的环境变量可以通过func_closure属性访问。例如:
output = '%s'w = x = y = z = 1def f1(): x = y = z = 2 def f2(): y = z = 3 def f3(): z = 4 print(output % ('w', id(w), w)) print(output % ('x', id(x), x)) print(output % ('y', id(y), y)) print(output % ('z', id(z), z)) return f3 return f2my_f3 = f3()print(my_f3)
运行结果显示,闭包会记录外部变量的引用。
总结来说,变量作用域和闭包是理解Python函数行为的关键概念。通过正确管理局部变量和闭包,可以编写更高效和可靠的代码。
转载地址:http://sxofk.baihongyu.com/