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开发 #程序员 #编程教程 #效率提升 #装饰器

相关推荐
好好学习啊天天向上6 小时前
C盘容量不够,python , pip,安装包的位置
linux·python·pip
时见先生6 小时前
Python库和conda搭建虚拟环境
开发语言·人工智能·python·自然语言处理·conda
二十雨辰6 小时前
[python]-循环语句
服务器·python
Yvonne爱编码6 小时前
Java 四大内部类全解析:从设计本质到实战应用
java·开发语言·python
wqwqweee6 小时前
Flutter for OpenHarmony 看书管理记录App实战:搜索功能实现
开发语言·javascript·python·flutter·harmonyos
-To be number.wan8 小时前
Python数据分析:numpy数值计算基础
开发语言·python·数据分析
Loo国昌9 小时前
深入理解 FastAPI:Python高性能API框架的完整指南
开发语言·人工智能·后端·python·langchain·fastapi
chinesegf9 小时前
Ubuntu 安装 Python 虚拟环境:常见问题与解决指南
linux·python·ubuntu
醉舞经阁半卷书19 小时前
Python机器学习常用库快速精通
人工智能·python·深度学习·机器学习·数据挖掘·数据分析·scikit-learn
开源技术10 小时前
Violit: Streamlit杀手,无需全局刷新,构建AI面板
人工智能·python