【Python】闭包

引入:

通过全局变量account_amount来记录余额

并定义函数进行取款存款操作,代码如下:

python 复制代码
account_amount = 0
def atm(num, deposit = True):
    global account_amount
    if deposit:
        account_amount += num
        print(f"存款:+{num},账户余额:{account_amount}")
    else:
        account_amount -= num
        print(f"取款:-{num},账户余额:{account_amount}")

atm(300)
atm(300)
atm(100, False)

运行结果:

复制代码
存款:+300,账户余额:300
存款:+300,账户余额:600
取款:-100,账户余额:500

尽管功能实现是OK的,但是仍有问题:

  • 代码在命名空间上(变量定义)不够干净、整洁
  • 全局变量有被修改的风险

如何解决?

  • 将变量定义在函数内部是行不通的
  • 我们需要使用闭包

我们先来看一个闭包的简单示例:

python 复制代码
def outer(logo):
    def inner(msg):
        print(f"<{logo}>{msg}<{logo}>")
    return inner

fn1 = outer("编程语言")
fn1("Python")
fn1("Java")
fn1("C++")

fn2 = outer("前端")
fn2("HTML")
fn2("CSS")
fn2("JavaScript")

运行结果:

复制代码
<编程语言>Python<编程语言>
<编程语言>Java<编程语言>
<编程语言>C++<编程语言>
<前端>HTML<前端>
<前端>CSS<前端>
<前端>JavaScript<前端>

定义双层嵌套函数,内层函数可以访问外层函数的变量

将内层函数作为外层函数的返回,此内层函数就是闭包函数

如果我们想修改外部函数的值呢?

使用nonlocal关键字

示例:

python 复制代码
def outer(num1):
    def inner(num2):
        nonlocal num1
        num1 += num2
        print(num1)
    return inner

fn = outer(10)
fn(5)
fn(3)
fn(1)

要对num1进行修改,需要用nonlocal对其进行修饰

运行结果:

复制代码
15
18
19

我们回过头来对一开始的代码进行优化:

python 复制代码
def account_create(initial_amount = 0):
    def atm(num, deposit =True):
        nonlocal initial_amount
        if deposit:
            initial_amount += num
            print(f"存款:+{num},账户余额:{initial_amount}")
        else:
            initial_amount -= num
            print(f"取款:-{num},账户余额:{initial_amount}")
    return atm

fn = account_create()
fn(300)
fn(300)
fn(100,False)

优点:

  • 无需定义全局变量即可实现:通过函数持续地访问、修改某个值
  • 闭包使用的变量的作用域在函数内,难以被错误的调用修改

缺点:

  • 由于内部函数持续引用外部函数的值,会导致这一部分内存空间不被释放,一直占用内存
相关推荐
默_笙3 天前
🍙 给每个请求过安检:FastAPI 是怎么把校验写进类型注解的
python
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
qq_426003963 天前
启动playwright录制codegen生成自动化测试脚本
python·自动化
虎头金猫3 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
长沙三为智能科技3 天前
家政小程序开发从0到上线:五阶段交付流程与验收清单
python
伞伞悦读3 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
只睡四小时3 天前
Canvas 弹道联机实战:700 行 + 固定时间步长
python·websocket·html5·游戏开发·canvas
C语言小火车3 天前
C/C++ 为什么需要编译器?
开发语言·c++
奇思妙想聪明勤奋的小羊3 天前
DeepAgents第5章:子Agent 与上下文隔离—让 Agent学会委派
人工智能·python·学习·语言模型
lpfasd1233 天前
2026年第38周GitHub趋势周报
python·科技·github