1 分钟读懂:Python 装饰器

每天1分钟,轻松懂 Python

这是一份有基础、有深度的 Python 核心技术手册

函数与闭包

1、函数是一等公民

Python 中函数可以赋值给变量;可以作为参数传递;也可以在函数里定义函数。

示例:将函数作为参数传递

python 复制代码
def func(message):  
    print(f"Got message: {message}")  

send_message = func  # 函数赋值给变量  
send_message("hello world")  # 这里调用:Got message: hello world  
2、函数嵌套与闭包

在函数内定义子函数,最后,返回子函数。在子函数可以访问外层函数变量。

python 复制代码
def outer():  
    x = 1  
    def inner():  
        print(x)  # 访问 outer 的变量 x  
    return inner  

fn = outer()  
fn()  # 输出 1(闭包保留外层变量引用 )  

核心语法

1、简单的装饰器

装饰器是用于 "包装函数",在不修改原函数的前提下,添加额外逻辑(如日志、权限校验 )。

python 复制代码
def my_decorator(func):  
    def wrapper():  
        print("wrapper of decorator")  
        func()  
    return wrapper  

@my_decorator  # 语法等价于 greet = my_decorator(greet)  
def greet():  
    print("hello world")  

greet()  
# 输出:  
# wrapper of decorator  
# hello world  
2、带参数的装饰器

*args**kwargs 可以接收任意数量和类型的参数。

python 复制代码
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print('wrapper of decorator')
        func(*args, **kwargs)
    return wrapper

@my_decorator
def greet(name, message):
    print(f"Hi {name}, {message}")


greet("Mr.Wang", "Good to see you.")

# 输出
# wrapper of decorator
# Hi Mr.Wang, Good to see you.

保留函数原信息

被装饰后函数,会默认丢失原信息(如 __name__ ),需要用 functools.wraps 修复:

python 复制代码
import functools  

def my_decorator(func):  
    @functools.wraps(func)  # 保留原函数信息 <<<<<<<<
    def wrapper(*args, **kwargs):  
        print("wrapper of decorator")  
        func(*args, **kwargs)  
    return wrapper  

@my_decorator  
def greet():  
    print("hello world")  

print(greet.__name__)  # 输出 'greet'(否则为 'wrapper' )  

类装饰器 和 多层装饰器

1、类装饰器

用类实现装饰器,通过 __call__ 方法拦截函数调用:

python 复制代码
class CountCalls:  
    def __init__(self, func):  
        self.func = func  
        self.num_calls = 0  

    def __call__(self, *args, **kwargs):  
        self.num_calls += 1  
        print(f"Call {self.num_calls} of {self.func.__name__}")  
        return self.func(*args, **kwargs)  

@CountCalls
def greet(name):
    print(f"Hi {name}")


greet("Mr.Wang")
# 输出:
# Call 1 of greet
# Hi Mr.Wang

greet("Mr.Li")
# 输出:
# Call 2 of greet
# Hi Mr.Li
2、多层装饰器

多个装饰器叠加,执行顺序为从外到内包裹,从内到外执行

python 复制代码
@decorator1  
@decorator2  
def greet():  
    print("hello world")  
    
# 执行逻辑等价于 greet = decorator1(decorator2(greet))  
# 执行时:decorator1 的 wrapper → decorator2 的 wrapper → 原函数  

使用场景

1、身份认证

校验用户登录状态,未登录则拦截操作:

python 复制代码
import functools  

def authenticate(func):  
    @functools.wraps(func)  
    def wrapper(*args, **kwargs):  
        if not check_login_state():  # 自定义校验逻辑
            raise Exception("Authentication failed")  
        return func(*args, **kwargs)  
    return wrapper  

@authenticate  
def post_comment(content):  
    print(f"发布评论:{content}")  
2、日志记录

统计函数执行时间、打印调用日志:

python 复制代码
import time  
import functools  

def log_execution_time(func):  
    @functools.wraps(func)  
    def wrapper(*args, **kwargs): 
        start = time.time()  
        result = func(*args, **kwargs)  
        end = time.time()  
        print(f"{func.__name__} 执行耗时:{end - start} 秒")  # 记录耗时
        return result  
    return wrapper  

@log_execution_time  
def train_model():  
    time.sleep(2)  # 模拟耗时操作  
3、输入合法性检查

预处理函数参数,确保符合规则:

python 复制代码
import functools  

def validate_params(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        # 示例:校验第一个参数为数字
        if not isinstance(args[0], (int, float)):  
            raise ValueError("参数必须为数字")
        return func(*args, **kwargs)

    return wrapper

@validate_params  
def process_data(data):  
    print(f"处理数据:{data}")  
4、缓存优化

@lru_cache 会缓存函数参数和结果,避免重复计算(如 functools.lru_cache ):

python 复制代码
import functools  

@functools.lru_cache(maxsize=128)
def cal(n):
    print(f"开始执行 cal. 参数:{n}")
    time.sleep(3)
    return n * 2


cal(100)
cal(100)
cal(100)

# 重复调用 cal(100) 时,只输出一个 "开始执行 cal. 参数:100"

-------- 写在最后 --------

关注我,每天1分钟,轻松懂 Python

我的同名公众号正在连载《FastAPI 开发实战》、《Python 核心技术》、《职场》。


点赞 :如果觉得有收获,点赞支持一下吧!

分享 :分享给身边同样对Python感兴趣的朋友!

关注我 :不要错过每一篇 Python 实战内容!


#Python #FastAPI #API #Web开发 #程序员 #编程教程 #效率提升 #装饰器

相关推荐
liliangcsdn5 分钟前
LLM如何与mcp server交互示例
linux·开发语言·python
Lupino7 分钟前
拯救迷失的荧光溶解氧传感器:从“三无”到“复活”的全记录
python
xcjbqd022 分钟前
SQL中视图能否嵌套存储过程_实现复杂自动化报表逻辑
jvm·数据库·python
ZC跨境爬虫23 分钟前
海南大学交友平台开发实战day7(实现核心匹配算法+解决JSON请求报错问题)
前端·python·算法·html·json
迷藏49425 分钟前
**发散创新:基于角色与属性的混合权限模型在微服务架构中的实战落地**在现代分布式系统中,
java·python·微服务·云原生·架构
与虾牵手36 分钟前
OpenClaw 和 AiPy 怎么选?2026 功能实测对比 + 踩坑全记录
python·ai编程
Csvn37 分钟前
🌟 LangChain 30 天保姆级教程 · Day 16|文档加载器大合集!PDF、Word、网页、数据库一键读取,构建你的知识库!
python·langchain
rebekk44 分钟前
claude工作区与git仓库的关系
linux·git·python
Huyuejia1 小时前
rag+agent主程序
python
jay神1 小时前
基于 YOLOv8 的PCB 缺陷检测系统
python·深度学习·yolo·目标检测·信息可视化·毕业设计