Python高阶精讲之闭包与装饰器彻底吃透(零基础看懂+实战源码)

 更新时间:2026年06月28日 10:13:00   作者:我材不敲代码  
本文详细解析Python闭包与装饰器,从基础到实战,覆盖闭包原理、装饰器本质、带参装饰器、企业级实战场景等,零基础也能快速掌握,希望对大家有所帮助

前言

很多Python开发者学了很久,依然看不懂装饰器、不会手写装饰器、不懂闭包原理

但闭包和装饰器是Python进阶分水岭:源码、框架(Flask/Django)、缓存、日志、接口鉴权、性能统计,底层全部依赖这套语法。

本文用最通俗的语言+分步拆解+完整实战源码,从零带你吃透:函数进阶 → 闭包原理 → 装饰器基础 → 有参装饰器 → 多层装饰器 → 企业级实战场景,零基础也能一次性学懂。

01 前置基础:函数是一等公民

Python中函数是一等对象(一等公民),拥有三个核心特性,这是闭包、装饰器能实现的根本:

  • 函数可以赋值给变量
  • 函数可以作为参数、返回值
  • 函数可以嵌套定义(内部函数)

基础示例

# 1. 函数赋值给变量
def hello():
    print("Hello Python")

f = hello
f()

# 2. 函数作为返回值
def outer():
    def inner():
        print("内部函数执行")
    return inner

res = outer()
res()

核心总结:正因为函数可以嵌套、可以返回,才诞生了闭包

02 闭包详解:定义、条件、原理

2.1 闭包的必备三要素

同时满足以下3点,就是闭包(Closure)

  • 函数嵌套(外层函数+内层函数)
  • 内层函数引用外层函数的局部变量
  • 外层函数返回内层函数

2.2 闭包实战代码

def outer(num):
    # 外层局部变量
    def inner():
        # 内层引用外层变量
        print(f"传入数值:{num}")
    return inner

# 接收内层函数
func = outer(100)
# 调用内层函数
func()

2.3 闭包核心特性(重点)

正常函数执行结束后,局部变量会被销毁释放

闭包会保留外层函数的局部变量,不会被GC回收,实现了数据常驻、状态保存

2.4 闭包经典场景:计数器

def count_factory():
    cnt = 0
    def counter():
        nonlocal cnt
        cnt += 1
        print(f"当前计数:{cnt}")
    return counter

c1 = count_factory()
c1()  # 1
c1()  # 2
c1()  # 3

知识点nonlocal 关键字,用于内层函数修改外层嵌套函数的局部变量。

03 装饰器本质:基于闭包的语法糖

3.1 核心认知

装饰器 = 高阶闭包 + 语法糖

装饰器的核心作用:在不修改原函数代码、不修改原函数调用方式的前提下,给函数新增功能

这就是设计模式中的开闭原则:对扩展开放,对修改关闭。

3.2 装饰器解决的问题

  • 避免重复代码(日志、计时、鉴权通用逻辑复用)
  • 业务代码与通用工具代码解耦
  • 统一项目规范,便于维护迭代

04 手写无参装饰器:日志统计实战

需求:给任意函数添加执行日志、执行耗时统计

4.1 原生闭包写法(理解底层)

import time

def timer_decorator(func):
    # 通用装饰器,接收任意参数
    def wrapper(*args, **kwargs):
        start = time.time()
        # 执行原函数
        res = func(*args, **kwargs)
        end = time.time()
        print(f"函数【{func.__name__}】执行耗时:{end - start:.4f}s")
        # 返回原函数结果
        return res
    return wrapper

# 测试函数
@timer_decorator
def calc_sum(n):
    s = 0
    for i in range(n):
        s += i
    return s

calc_sum(100000)

4.2 装饰器执行流程拆解

  • @timer_decorator 装饰器加载,等价于 calc_sum = timer_decorator(calc_sum)
  • 调用 calc_sum() 实际执行的是内部包装函数 wrapper()
  • wrapper执行前置逻辑 → 执行原函数 → 后置逻辑 → 返回结果

4.3 解决函数信息覆盖问题

直接使用装饰器会导致原函数的函数名、文档注释被wrapper覆盖,需要 functools.wraps 修复:

import time
from functools import wraps

def timer_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        end = time.time()
        print(f"函数【{func.__name__}】执行耗时:{end - start:.4f}s")
        return res
    return wrapper

05 进阶:带参数装饰器 + 多层装饰器

5.1 带参数装饰器

普通装饰器只能接收函数参数,带参装饰器可以自定义配置参数,灵活性更高。

需求:自定义日志等级,控制是否打印日志

from functools import wraps

def log_decorator(switch=True):
    # 外层接收装饰器参数
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if switch:
                print(f"【日志】函数{func.__name__}开始执行")
            res = func(*args, **kwargs)
            return res
        return wrapper
    return decorator

# 开启日志
@log_decorator(switch=True)
def test_func():
    print("业务逻辑执行")

test_func()

5.2 多层装饰器叠加执行顺序

加载顺序:自下而上执行顺序:自上而下

口诀:先装饰的后执行,后装饰的先执行

from functools import wraps

def deco1(func):
    @wraps(func)
    def wrapper():
        print("deco1 前置")
        func()
        print("deco1 后置")
    return wrapper

def deco2(func):
    @wraps(func)
    def wrapper():
        print("deco2 前置")
        func()
        print("deco2 后置")
    return wrapper

@deco1
@deco2
def hello():
    print("核心业务执行")

hello()

06 企业级实战三大装饰器(可直接复用)

6.1 接口鉴权装饰器

from functools import wraps

def login_auth(func):
    @wraps(func)
    def wrapper(user_token, *args, **kwargs):
        # 模拟鉴权逻辑
        if not user_token:
            return {"code": 401, "msg": "未登录,权限不足"}
        return func(user_token, *args, **kwargs)
    return wrapper

# 模拟接口
@login_auth
def get_user_info(token):
    return {"code": 200, "data": "用户信息数据"}

print(get_user_info(""))

6.2 简易缓存装饰器(避免重复计算)

from functools import wraps

def cache_decorator(func):
    cache = {}
    @wraps(func)
    def wrapper(*args):
        if args not in cache:
            cache[args] = func(*args)
        return cache[args]
    return wrapper

@cache_decorator
def fib(n):
    if n <= 2:
        return 1
    return fib(n-1) + fib(n-2)

print(fib(30))  # 首次计算,后续直接读取缓存

6.3 异常捕获装饰器(统一异常处理)

from functools import wraps

def exception_catch(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            print(f"【函数异常】{func.__name__}执行失败:{str(e)}")
            return None
    return wrapper

@exception_catch
def divide(a, b):
    return a / b

divide(10, 0)

07 面试高频真题(必背)

Q1:什么是闭包?闭包的作用和缺点?

答:

闭包是嵌套函数中,内层函数引用外层局部变量、外层返回内层函数的代码结构。

作用:保存函数执行状态、实现数据常驻、简化代码、实现装饰器。

缺点:外层变量常驻内存无法释放,长期使用会造成内存泄漏

Q2:装饰器的原理是什么?为什么不修改原代码?

装饰器基于闭包+高阶函数实现,通过包装原函数,在函数执行前后扩展逻辑,符合开闭原则,实现业务与通用逻辑解耦。

Q3:wraps装饰器的作用?

修复装饰器导致的原函数信息丢失问题,保留原函数的 __name__、文档注释等属性。

Q4:多层装饰器的执行顺序?

加载自下而上,执行自上而下,先装饰的函数最后执行后置逻辑。

到此这篇关于Python高阶精讲之闭包与装饰器彻底吃透(零基础看懂+实战源码)的文章就介绍到这了,更多相关Python闭包与装饰器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 一文详解Python中PO模式的设计与实现

    一文详解Python中PO模式的设计与实现

    在使用 Python 进行编码的时候,会使用自身自带的编码设计格式,比如说最常见的单例模式等。本文将为大家介绍PageObject自动化设计模式(PO模式)的设计与实现,感兴趣的可以了解一下
    2022-06-06
  • Python错误和异常总结详细

    Python错误和异常总结详细

    本文详细且清晰地讲解了Python中错误和异常的概念及其处理方式,通过具体案例展示try...except、try...finally、with...等句式的具体用法,期望能帮助到对此感到迷惑的初学者
    2021-10-10
  • 使用Python实现将HTML内容格式插入Word文档

    使用Python实现将HTML内容格式插入Word文档

    在日常开发和业务流程中,我们经常需要生成包含复杂格式和动态内容的Word文档,本文将介绍如何使用Python实现将HTML内容格式插入Word文档,感兴趣的小伙伴可以了解下
    2026-01-01
  • Python 串口读写的实现方法

    Python 串口读写的实现方法

    今天小编就为大家分享一篇Python 串口读写的实现方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-06-06
  • python MultipartEncoder传输zip文件实例

    python MultipartEncoder传输zip文件实例

    这篇文章主要介绍了python MultipartEncoder传输zip文件实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • opencv图片处理常见操作方法总结

    opencv图片处理常见操作方法总结

    这篇文章主要介绍了opencv图片处理常见操作方法的相关资料,通过代码示例,展示了如何对图片进行这些操作,并解释了图片在计算机中以数组形式存储的原理,需要的朋友可以参考下
    2026-01-01
  • Python实现语音启动电脑应用程序

    Python实现语音启动电脑应用程序

    这篇文章主要为大家详细介绍了如何使用Python实现语音启动电脑应用程序功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一学习一下
    2025-03-03
  • Python绘图实现显示中文

    Python绘图实现显示中文

    今天小编就为大家分享一篇Python绘图实现显示中文,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • pandas 强制类型转换 df.astype实例

    pandas 强制类型转换 df.astype实例

    这篇文章主要介绍了pandas 强制类型转换 df.astype实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • Flask类视图的基本用法及高级技巧

    Flask类视图的基本用法及高级技巧

    Flask的类视图提供了一种强大而灵活的方式来构建Web应用的业务逻辑,本文主要介绍了Flask类视图的基本用法及高级技巧,感兴趣的可以了解一下
    2024-01-01

最新评论