一文搞懂Python装饰器,还能用它给代码加权限锁!

听到"装饰器"三个字总觉得是高深莫测的东西。网上各种教程一上来就是@符号、嵌套函数、闭包这些术语,看得人一头雾水。今天咱们就用大白话,把这个玩意儿讲讲明白喽,最后咱们再简单的写一个权限验证的装饰器。

一、从小白开始:什么是装饰器?

简单来说,装饰器就是给已有的函数"加外挂"的工具。比如你有一个函数,突然想给它增加记录运行时间的功能,但又不想修改这个函数本身的代码。这时候就能用上装饰器了。

装饰器就像给手机加个保护壳------手机本身没变,但多了层保护。在Python中,装饰器就是用@符号表示的那个东西。

先来看个最简单的例子:

python 复制代码
import functools
def log_decorator(func):
    """日志装饰器"""

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print(f"调用参数:{func.__name__}")
        print(f"参数:{args};kwargs={kwargs}")
        result = func(*args, **kwargs)
        print(f"返回值:{result}")
        return result

    return wrapper


# 使用装饰器
@log_decorator
def calculate_sum(n):
    return sum(range(1, n + 1))


# 进行测试
result = calculate_sum(1000)
print(f"最终结果:{result}")

运行结果:

看明白了吗?log_decorator就像是给calculate_sum函数包了一层外挂,在函数执行前后加了点"佐料"。

二、进阶一点:装饰器是怎么工作的?

其实上面的@语法糖只是一种简便写法,本质上等价于:

python 复制代码
def calculate_sum(n):
    return sum(range(1, n + 1))

result = log_decorator(calculate_sum(n))

装饰器接收一个函数作为参数,然后返回一个新的函数来替代原来的函数。

三、带参数的装饰器

有时候我们想让装饰器本身也能接受参数。比如想要一个能重复执行函数指定次数的装饰器:

python 复制代码
def repeat(times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for i in range(times):
                print(f"第{i+1}次执行")
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(times=3)
def say_hello():
    print("Hello!")

say_hello()

这里实际上有三层嵌套:最外层的repeat接收参数,返回一个装饰器函数decorator;decorator接收函数,返回wrapper函数。

四、实战:用装饰器实现权限验证

现在我们来点实际的。假设我们正在开发一个Web应用,有些页面需要登录才能访问,有些需要管理员权限。用装饰器来实现这个需求再合适不过了。

首先定义用户类型:

python 复制代码
USER_ROLES = {
    'anonymous': 0,    # 匿名用户
    'user': 1,         # 普通用户
    'admin': 2         # 管理员
}

class User:
    def __init__(self, name, role):
        self.name = name
        self.role = role

current_user = User('张三', USER_ROLES['user'])  # 模拟当前用户

然后编写权限验证装饰器:

python 复制代码
def require_login(func):
    def wrapper(*args, **kwargs):
        if current_user.role == USER_ROLES['anonymous']:
            return "请先登录!"
        return func(*args, **kwargs)
    return wrapper

def require_admin(func):
    def wrapper(*args, **kwargs):
        if current_user.role < USER_ROLES['admin']:
            return "需要管理员权限!"
        return func(*args, **kwargs)
    return wrapper

现在我们可以轻松给函数加权限控制了:

python 复制代码
@require_login
def view_profile():
    return f"查看{current_user.name}的个人资料"

@require_admin  
def delete_user(user_id):
    return f"删除用户{user_id}成功"

print(view_profile())  # 正常访问
# print(delete_user(123))  # 需要管理员权限!

如果当前用户是普通用户,第一个函数能正常执行,第二个会返回"需要管理员权限!"的提示。

五、更好的方式:一个装饰器搞定多种权限

上面的写法虽然能用,但如果权限类型很多,我们要写很多类似的装饰器。我们可以改进一下,让一个装饰器支持多种权限级别:

python 复制代码
def require_role(required_role):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if current_user.role < required_role:
                role_name = [k for k, v in USER_ROLES.items() if v == required_role][0]
                return f"需要{role_name}权限!"
            return func(*args, **kwargs)
        return wrapper
    return decorator

# 使用方式
@require_role(USER_ROLES['user'])
def view_profile():
    return f"查看{current_user.name}的个人资料"

@require_role(USER_ROLES['admin'])
def delete_user(user_id):
    return f"删除用户{user_id}成功"

这样代码更加简洁和灵活了。

六、啰嗦一句

装饰器是Python中非常强大的特性,它允许我们不修改原有代码的情况下给函数添加新功能。从最简单的无参装饰器,到带参数的装饰器,再到今天的权限验证实战,希望大家对装饰器有更深的理解。

记住装饰器的核心思想:不修改原有代码,通过包装的方式扩展功能。


相关推荐
Li Ming&6 分钟前
Python办公自动化:利用Python批量将PDF转换为图片文件
python·pdf·pip
她说彩礼65万29 分钟前
Asp.net core 模型绑定
后端·asp.net
Anova.YJ30 分钟前
AI Notebook
人工智能·python·机器学习
用户342323237631734 分钟前
BLE 传感器节点实战
后端
疯狂成瘾者35 分钟前
Java 常见集合方法
java·windows·python
web守墓人37 分钟前
【python】uv解决依赖安装缓慢的问题
开发语言·python·uv
asdzx6739 分钟前
使用 Python 精准操控 Word 字体:获取与替换方案
python·c#·word
胡耀超39 分钟前
固件逆向:从一坨二进制,到一个可以被解释的系统
python·逆向工程·硬件安全·二进制分析·电子数据取证·嵌入式安全·固件逆向
fliter41 分钟前
Go 1.26 新增 `bytes.Buffer.Peek`:只看数据,不移动读取位置
后端
羑悻1 小时前
我受够了 Coding Agent 的“假聪明,真串行”,于是做了 Meta-Orchestrator!
后端