博客
关于我
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 嵌套字典全面指南
查看>>
Python 工具v简介
查看>>
Python编程入门指南:从零开始探索编程的奇妙世界
查看>>
python 常见内置函数setattr、getattr、delattr、setitem、getitem、delitem
查看>>
Python 常见的错误类型和继承关系
查看>>
python 常量_零基础学Python系列之一:Python的变量与常量
查看>>
Python 并发编程
查看>>
Python编程入门基础及高级技能、Web开发、数据分析和机器学习与人工智能
查看>>
python 序列化操作
查看>>
Python 开发者,这 7 个 VS Code 插件极力推荐
查看>>
python手把手视频_硬货 | 手把手带你构建视频分类模型(附Python演练))
查看>>
python 录音左右声道_Python分离立体声wav压缩文件的左右声道
查看>>
Python 循环异或对文件进行加解密
查看>>
Python开发环境搭建(附VMware安装包及虚拟机环境)
查看>>
python 微信扫码登录_python实现微信第三方网站扫码登录(Django)
查看>>
Python 快速下载依赖
查看>>
python实现非参数统计的Cochran检验 (附完整源码)
查看>>
python 怎么验证是否安装成功 scrapy
查看>>
Python 手写数字识别-1
查看>>
Python实现接口自动化测试库(JSON与Requests)详解
查看>>