博客
关于我
Python基础:11变量作用域和闭包
阅读量:796 次
发布时间:2023-03-07

本文共 2573 字,大约阅读时间需要 8 分钟。

变量作用域与闭包

在编程中,变量的作用域是理解代码行为的关键概念。一个变量可以属于局部作用域或全局作用域。定义在函数内的变量具有局部作用域,而在模块最高级别定义的变量则属于全局作用域。

全局变量的特点是除非被显式删除,否则它们会一直存在到脚本运行结束,并且可以在所有函数中访问。相比之下,局部变量的生命周期仅取决于其定义函数的执行阶段。

在Python中,变量查找遵循局部-外部-全局-内建(LEGB)的顺序优先级。在局部作用域未找到变量时,才会在外部作用域、全局作用域和内建作用域中依次查找。如果仍未找到,则会抛出NameError异常。因此,局部变量可以“隐藏”或覆盖全局变量。

由于闭包和嵌套函数的引入,作用域的层次变得更复杂。变量查找的优先级顺序变为:局部、外部、全局和内建。需要注意的是,只有defclasslambda等语句会产生新的作用域,而iftryfor等语句不会创建新的作用域。

例如,在以下函数中,变量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 bar
UnboundLocalError: 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 line
my_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 incr
count = counter(5)
print(count()) # 输出 6
print(count()) # 输出 7
count2 = counter(100)
print(count2()) # 输出 101
print(count()) # 输出 8

闭包会携带外部函数的环境变量。

需要注意的是,闭包不能直接修改外部变量,除非使用nonlocal关键字(Python3引入)。例如:

def counter2(start_at=0):
count = start_at
def incr():
count += 1
return count
return incr
count = counter2(5)
print(count()) # 会抛出UnboundLocalError

此外,闭包的环境变量可以通过func_closure属性访问。例如:

output = '
%s
'
w = x = y = z = 1
def 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 f2
my_f3 = f3()
print(my_f3)

运行结果显示,闭包会记录外部变量的引用。

总结来说,变量作用域和闭包是理解Python函数行为的关键概念。通过正确管理局部变量和闭包,可以编写更高效和可靠的代码。

转载地址:http://sxofk.baihongyu.com/

你可能感兴趣的文章
Python 操作sqlite数据库及保存查询numpy类型数据(二)
查看>>
Python 操作数据库
查看>>
Python 数据分析与可视化实战
查看>>
python 数据可视化 -- matplotlib02
查看>>
python 数据可视化利器
查看>>
Python 数据可视化详解
查看>>
python 数据库查询返回list或tuple
查看>>
Python 数据库连接池管理的基本知识 (附Demo)
查看>>
Python学习记录-2016-12-17
查看>>
Python 数据库骚操作 -- MySQL
查看>>
Python 数据操作详解
查看>>
Python 数据文件与网络数据序列化存储详解
查看>>
Python 数据结构与算法详解
查看>>
Python 数据采集、清洗、整理、分析以及可视化实战
查看>>
Python 数据预处理
查看>>
python 文件类型检测 linux和windows都可以用
查看>>
Python多处理池,加入;不等待继续?
查看>>
Python多处理帮助在条件下退出
查看>>
Python 无法安装包
查看>>
python 日历小部件 - 返回用户选择的日期
查看>>