【自记】Python 中 nonlocal 和 global 的区别,以及闭包的作用和示例

一、nonlocalglobal 的区别

作用范围
  • global :用于在函数内部声明一个变量是全局变量。如果在函数中使用 global 关键字声明了某个变量,那么在函数内部对该变量的操作,就是对全局作用域中这个变量的操作。例如:
python 复制代码
count = 10
def modify_count():
    global count
    count = 20
    print(count)

modify_count()  # 输出 20
print(count)    # 输出 20,全局变量count已经被修改
  • nonlocal :用于在嵌套函数中,声明一个变量不是当前函数的局部变量,而是来自外层(非全局)函数的变量。它使得内层函数可以修改外层函数中定义的变量,前提是外层函数中没有使用 global 声明这个变量。比如:
python 复制代码
def outer():
    num = 5
    def inner():
        nonlocal num
        num = 10
        print(num)
    inner()
    print(num)

outer()  
# 输出 10
# 输出 10,因为内层函数通过nonlocal修改了外层函数的num变量
适用场景
  • global:当需要在函数内部修改全局作用域中的变量时使用。
  • nonlocal:在函数嵌套的场景下,内层函数想要修改外层函数中定义的变量,且该变量不是全局变量时使用。

二、闭包的作用

数据隐藏与封装

闭包可以将一些数据(即外层函数的变量)与操作这些数据的函数绑定在一起,形成一个相对独立的单元,外界不能直接访问这些被 "隐藏" 的数据,只能通过闭包返回的函数来操作。例如,实现一个简单的计数器:

python 复制代码
def counter():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

count_func = counter()
print(count_func())  # 输出 1
print(count_func())  # 输出 2
print(count_func())  # 输出 3

在这个例子中,count 变量被隐藏在闭包内部,外界无法直接访问和修改,只能通过 increment 函数来对其进行递增操作,实现了数据的封装。

状态保持

闭包可以 "记住" 外层函数执行时的变量状态,方便在多次调用返回的函数时,基于之前的状态进行操作。比如模拟一个累加器:

python 复制代码
def accumulator(initial_value=0):
    def accumulate(num):
        nonlocal initial_value
        initial_value += num
        return initial_value
    return accumulate

acc = accumulator(5)
print(acc(3))  # 输出 8,初始值5加上传入的3
print(acc(2))  # 输出 10,基于上一次结果8再加上传入的2

这里闭包记住了 initial_value 的状态,每次调用 accumulate 函数时,都是基于上一次的状态进行累加操作。

函数复用

闭包可以创建具有特定初始状态的函数,方便在不同场景下复用。比如创建不同税率的计算函数:

python 复制代码
def tax_calculator(tax_rate):
    def calculate_tax(amount):
        return amount * tax_rate
    return calculate_tax

calculate_sales_tax = tax_calculator(0.08)  # 8% 的销售税
calculate_income_tax = tax_calculator(0.2)  # 20% 的所得税
print(calculate_sales_tax(100))  # 输出 8
print(calculate_income_tax(1000))  # 输出 200

通过 tax_calculator 函数创建不同税率的计算函数,这些函数都能复用内部计算逻辑,只是初始的税率不同。

三、注意

在 Python 中,内部函数本来就可以 "读取" 外层函数的变量(包括参数),但只有通过 nonlocal 声明后,才能 "修改" 外层函数的变量

相关推荐
青 春 记 忆22 分钟前
LeetCode 121. 买卖股票的最佳时机|Python 解法详解
python·算法·leetcode
满怀冰雪26 分钟前
21-图像分类实战:从 MNIST 到 CIFAR-10
人工智能·python·深度学习·分类·数据挖掘·paddlepaddle
Logintern0935 分钟前
Celery 的底层架构正是进程池、事件循环、epoll 和协程全部组合在了一起
python·架构·消息队列·进程·celery·事件循环
用户03321266636736 分钟前
在 Word 文档快速中插入图片【Python 教程】
python
盖伦发发41 分钟前
RAG 能跑≠能用:用 EDD 把 Eval 做成基础设施 (附源码)
人工智能·后端·python·功能测试
郝学胜_神的一滴1 小时前
Python 高级编程 028:字典dict从入门到精通
python·ai编程
weixin_BYSJ19871 小时前
springboot小区物业管理小程序---附源码45555
java·javascript·spring boot·python·django·flask·php
a-6262 小时前
三维重建的步骤-1(采集的是环绕物体均匀旋转一圈的视频)
python·pycharm·三维重建·metashape
qq_22589174662 小时前
基于Flask的空气质量监测与预测分析系统
开发语言·后端·python·信息可视化·django·flask
Dxy12393102163 小时前
Python XPath position() 完整使用指南,避坑合集(lxml适用)
前端·javascript·python