Python 闭包与装饰器 超详细精讲

一、前言:为什么要学闭包和装饰器?

闭包是函数高级用法,装饰器是Python 最优雅的语法糖。
学会它们,你能写出:

  • 更简洁的代码
  • 不修改原函数就能增加功能
  • 日志、计时、权限、缓存等通用功能
  • 符合企业级开发规范的代码

闭包是基础,装饰器是闭包的经典应用。


二、什么是闭包(Closure)?

1. 闭包定义(最通俗)

  1. 函数里面定义了内部函数
  2. 内部函数使用了外部函数的变量
  3. 外部函数返回内部函数名
    满足这 3 点 = 闭包

2. 闭包三要素(必须背会)

  • 外部函数嵌套内部函数
  • 内部函数使用外部函数的变量
  • 外部函数返回内部函数

3. 最简单闭包代码

# 外部函数
def outer(x):
    # 外部函数变量
    a = x

    # 内部函数(闭包核心)
    def inner():
        # 使用外部函数变量
        return a + 10

    # 返回内部函数
    return inner

# 创建闭包实例
func = outer(5)
# 调用内部函数
print(func())  # 15

4. 闭包特点

  • 内部函数可以记住外部函数的环境
  • 外部函数执行完毕,变量不会被销毁
  • 可以实现数据隐藏和函数工厂

三、闭包经典案例:计数器

def counter():
    count = 0  # 外部变量

    def add():
        nonlocal count  # 声明修改外部变量
        count += 1
        return count

    return add

# 创建计数器
c = counter()
print(c())  # 1
print(c())  # 2
print(c())  # 3

✅ 闭包让 count 变量一直保存在内存中


四、什么是装饰器(Decorator)?

1. 装饰器定义

  • 在不修改原函数代码的前提下,给函数增加新功能
  • 本质是闭包 + 语法糖 @
  • 装饰器 = 闭包的实际应用

2. 装饰器作用

  • 日志记录
  • 执行时间统计
  • 权限验证
  • 缓存
  • 参数检查

3. 装饰器语法

@装饰器名字
def 原函数():
     pass

五、最简单装饰器(一步步写)

第1步:写装饰器(闭包)

# 装饰器函数
def my_decorator(func):
    def wrapper():
        print("函数执行前 —— 新增功能")
        func()  # 调用原函数
        print("函数执行后 —— 新增功能")
    return wrapper

第2步:写原函数

def say_hello():
    print("Hello World")

第3步:使用装饰器

# 装饰
say_hello = my_decorator(say_hello)
# 调用
say_hello()

运行结果

函数执行前 —— 新增功能
Hello World
函数执行后 —— 新增功能

六、语法糖 @ 写法(最常用)

def my_decorator(func):
    def wrapper():
        print("函数执行前")
        func()
        print("函数执行后")
    return wrapper

# 使用 @ 语法糖
@my_decorator
def say_hello():
    print("Hello World")

say_hello()

✅ 效果一样,代码更优雅!


七、带参数的函数 + 装饰器

def my_decorator(func):
    # wrapper 接收参数
    def wrapper(a, b):
        print("计算开始")
        func(a, b)
        print("计算结束")
    return wrapper

@my_decorator
def add(a, b):
    print(f"{a} + {b} = {a + b}")

add(10, 20)

运行结果

计算开始
10 + 20 = 30
计算结束

八、万能装饰器(适配所有函数)

使用 *args 和 **kwargs 适配任意参数、任意返回值

def decorator(func):
    def wrapper(*args, **kwargs):
        print("===== 功能开始 =====")
        result = func(*args, **kwargs)
        print("===== 功能结束 =====")
        return result
    return wrapper

@decorator
def add(a, b):
    return a + b

print(add(1, 2))

九、装饰器经典案例:计时功能

计算函数执行时间(企业最常用)

import time

# 计时装饰器
def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        end = time.time()
        print(f"函数执行耗时:{end - start:.4f} 秒")
        return res
    return wrapper

@timer
def test():
    time.sleep(1)

test()

十、装饰器经典案例:日志功能

def log(func):
    def wrapper(*args, **kwargs):
        print(f"调用函数:{func.__name__}")
        print(f"参数:{args} {kwargs}")
        return func(*args, **kwargs)
    return wrapper

@log
def add(a, b):
    return a + b

add(10, 20)

十一、多个装饰器叠加

def decorator1(func):
    def wrapper():
        print("装饰器1 —— 前")
        func()
        print("装饰器1 —— 后")
    return wrapper

def decorator2(func):
    def wrapper():
        print("装饰器2 —— 前")
        func()
        print("装饰器2 —— 后")
    return wrapper

# 执行顺序:从上到下装饰,从内到外执行
@decorator1
@decorator2
def func():
    print("我是原函数")

func()

十二、带参数的装饰器(高级)

def log_level(level):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(f"[{level}] 执行函数")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@log_level("INFO")
def test():
    print("Hello")

test()

十三、闭包 vs 装饰器(总结表)

名称 关系 作用 形式
闭包 基础 保存数据、嵌套函数 外函数返内函数
装饰器 闭包应用 增强函数功能 @xxx

十四、 重点总结

  1. 闭包 = 嵌套函数 + 使用外部变量 + 返回内部函数
  2. 闭包可以记住外部环境,延长变量生命周期
  3. 装饰器 = 闭包 + 语法糖 @
  4. 装饰器不修改原函数,就能增加功能
  5. 万能装饰器使用 *args, **kwargs
  6. 常用场景:计时、日志、权限、缓存
posted @ 2026-04-05 15:26  Petula  阅读(221)  评论(0)    收藏  举报