Python核心概念解析:闭包、深浅拷贝、垃圾回收与with语句

Finn
Finn
发布时间:2026-10-14| 5人浏览过
原创

本文系统梳理Python四大核心概念:解析闭包的定义、特点及变量修改方法;对比浅拷贝与深拷贝在内存引用上的差异;详解引用计数、标记-清除及分代回收三种垃圾回收机制;阐述with语句作为上下文管理协议在资源释放中的应用。

Python闭包详解

1.1 闭包

1、闭包概念

1. 当在一个外部函数内部定义一个内部函数,且该内部函数引用了外部函数的临时变量,同时外部函数返回内部函数的引用时,便构成了一个闭包。

2. 通常情况下,函数执行结束后,其内部所有资源会被释放并归还给内存,局部变量随之消失。

3. 然而,闭包是一种特殊情况:如果外部函数在结束时发现其临时变量将在内部函数中被使用,它会将这些临时变量绑定到内部函数上,随后自身再结束执行。

2、闭包特点

1. 必须包含一个内嵌函数。

2. 内嵌函数必须引用外部函数中的变量。

3. 外部函数的返回值必须是内嵌函数。

闭包实例


#闭包函数的实例
def outer( a ):
 b = 10
 def inner():  # 在内函数中 用到了外函数的临时变量
 print(a+b) # 外函数的返回值是内函数的引用
 return inner

if __name__ == '__main__':
 demo = outer(5)
 demo() # 15

# 在这里我们调用外函数传入参数5
# 此时外函数两个临时变量 a是5 b是10 ,并创建了内函数,然后把内函数的引用返回存给了demo
# 外函数结束的时候发现内部函数将会用到自己的临时变量,这两个临时变量就不会释放,会绑定给这个内部函数
# 我们调用内部函数,看一看内部函数是不是能使用外部函数的临时变量
# demo存了外函数的返回值,也就是inner函数的引用,这里相当于执行inner函数

闭包实例

3、闭包中内函数修改外函数局部变量

1、在基础Python语法中,函数可以随意读取全局数据,但修改全局数据时有两种方法:

1) 使用 global 关键字声明全局变量。

2) 当全局变量为可变类型数据时,可以直接修改。

2、在闭包场景下,可采用以下两种方法进行修改:

1) 在Python 3中,可使用 nonlocal 关键字声明一个变量,表示该变量不属于当前局部变量空间,需向上一级变量空间查找。

2) 在Python 2中,由于没有 nonlocal 关键字,可将闭包变量改为可变类型数据(如列表)进行修改。

修改闭包变量


#修改闭包变量的实例
def outer( a ):
 b = 10  # a和b都是闭包变量
 c = [a]  # 这里对应修改闭包变量的方法2
 def inner():
 # 方法一: nonlocal关键字声明(python3)
 nonlocal b
 b+=1

 # 方法二: 把闭包变量修改成可变数据类型 比如列表(python2)
 c[0] += 1
 print(c[0])
 print(b)
 return inner  # 外函数的返回值是内函数的引用

if __name__ == '__main__':
 demo = outer(5)
 demo()  # 6 11

闭包中内函数修改外函数局部变量

Python深浅拷贝解析

1.2 Python里的拷贝

1、预备知识一——python的变量及其存储

1. Python中所有变量均为对象,变量存储采用引用语义,即存储的是变量值所在的内存地址,而非变量本身。

2. 无论数据结构多么复杂,浅拷贝仅会复制一层。

理解:如同两人共用一张桌子,只要桌子本身不变,桌上菜肴的变化两人均能共同感知。

浅拷贝示例


>>> str1 = 'hello'
>>> str2 = str1

#1、让str1和str2变量都存储了‘hello'所在的内存地址
>>> id(str1)
>>> id(str1)
>>>

#2、当str1的值变成‘new hello'后str1的值被重新赋值成'new hello'的内存地址,而str2的值依旧是‘hello'的内存地址
>>> str1 = 'new hello'
>>> id(str1)
>>> id(str2)

#3、不管多么复杂的数据结构,浅拷贝都只会copy一层。
>>> sourceList = [1,2,[3,4]]
>>> newList = sourceList

>>> l[2][0]=100

>>> sourceList
[1, 2, [100, 4]]
>>> newList
[1, 2, [100, 4]]

不管多么复杂的数据结构,浅拷贝都只会copy一层

2、浅copy与deepcopy

1、浅copy:无论数据结构多么复杂,浅拷贝仅复制一层。

2、deepcopy:深拷贝会完全复制原变量相关的所有数据,在内存中生成一套完全相同的内容,对其中任意一个变量的修改不会影响另一个变量。

深拷贝示例


import copy
sourceList = [1,2,3,[4,5,6]]
copyList = copy.copy(sourceList)
deepcopyList = copy.deepcopy(sourceList)

sourceList[3][0]=100

print(sourceList)  # [1, 2, 3, [100, 5, 6]]
print(copyList)  # [1, 2, 3, [100, 5, 6]]
print(deepcopyList)  # [1, 2, 3, [4, 5, 6]]

浅copy与deepcopy

Python垃圾回收机制

1.3 Python垃圾回收机制

垃圾回收机制:https://www.jb51.net/article/168707.htm

1、引用计数

1. 原理

1) 当创建或复制对象引用时,对象的引用计数加1;当引用被销毁时,引用计数减1。

2) 当对象引用计数降为0时,意味着对象不再被使用,可释放其内存。

2. 优点

引用计数的最大优点是实时性:任何内存一旦没有指向它的引用,便会立即被回收,而其他垃圾收集技术需在特定条件下才能回收无效内存。

3. 缺点

1) 维护引用计数带来的额外操作与Python运行中的内存分配、释放及引用赋值次数成正比。

2) 这显然比其他仅与待回收内存数量相关的垃圾收集技术效率更低。

3) 由于对象间相互引用,每个对象的引用计数均不为0,导致这些对象占用的内存始终无法释放。

2、标记-清除

1. 说明

1) 分为两个阶段:第一阶段为标记阶段,GC将所有活动对象打上标记;第二阶段回收未标记的非活动对象。

2) 对象通过引用(指针)连接,构成一个有向图。

3) 从根对象(root object)出发,沿有向边遍历对象,可达的对象标记为活动对象,不可达的对象即为需清除的非活动对象。

根对象包括全局变量、调用栈、寄存器。

注:像PyIntObject、PyStringObject等不可变对象不可能产生循环引用,因为它们内部不持有其他对象的引用。

1. 在上图中,程序变量可直接访问块1,并间接访问块2和3,但无法访问块4和5。

2. 第一步标记块1,并记住块2和3以供后续处理。

3. 第二步标记块2,第三步标记块3,但不再记住块2,因其已被标记。

4. 扫描阶段忽略已标记的块1、2和3,但会回收块4和5。

2、缺点

1) 标记清除算法作为Python的辅助垃圾收集技术,主要处理容器对象(如list、dict、tuple等)。

因为字符串、数值对象不可能造成循环引用问题。

2) 在清除非活动对象前,必须顺序扫描整个堆内存,即使仅剩小部分活动对象,也要扫描所有对象。

3、分代回收

1. 分代回收建立在标记清除技术之上,是一种以空间换时间的操作方式。

2. Python将内存分为3“代”:年轻代(第0代)、中年代(第1代)、老年代(第2代)。

3. 它们对应3个链表,垃圾收集频率随对象存活时间增加而降低。

4. 新创建的对象分配在年轻代,当年轻代链表总数达到上限时,Python垃圾收集机制触发。

5. 回收可回收对象,不可回收的对象移至中年代,依此类推。

6. 老年代中的对象是存活时间最久的对象,甚至存活于整个系统生命周期内。

上下文管理with语句

1.4 上下文管理(with)

1、什么是with语句

1. with是一种上下文管理协议,旨在从流程图中移除try、except和finally关键字及相关资源分配释放代码,简化处理流程。

2. 因此,使用with处理的对象必须具有enter()和exit()这两个方法。

1) with通过enter方法初始化(enter方法在语句体执行前进入运行)。

2) 然后在exit中执行善后及处理异常(exit()方法在语句体执行完毕后退出时运行)。

2、with语句使用场景

1. with语句适用于访问资源的场合,确保无论过程中是否发生异常,都会执行必要的“清理”操作以释放资源。

2. 例如文件使用后自动关闭、线程中锁的自动获取和释放等。

3、with处理文件操作的实例

文件操作实例


with open('/etc/passwd') as f:
 for line in f:
 print(line)
 # 这段代码的作用:打开一个文件,如果一切正常,把文件对象赋值给f,然后用迭代器遍历文件中每一行,当完成时,关闭文件;

 # 而无论在这段代码的任何地方,如果发生异常,此时文件仍会被关闭。

到此这篇关于python闭包、深浅拷贝、垃圾回收、with语句知识点汇总的文章就介绍到这了,更多相关python闭包&深浅拷贝&垃圾回收&with语句内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。