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

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


相关推荐
红尘散仙2 小时前
我把终端小说阅读器接上了 AI Agent:TRNovel 现在能用 skill 生成书源了
人工智能·后端·rust
心中有国也有家2 小时前
GE图引擎深度解析——CANN的计算图优化与执行引擎
人工智能·pytorch·python·学习·numpy
卷毛的技术笔记4 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
编程大师哥4 小时前
匿名函数 lambda + 高阶函数
java·python·算法
vb2008114 小时前
FastAPI APIRouter
开发语言·python
会编程的土豆4 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
adrninistrat0r4 小时前
Java调用链MCP分析工具
java·python·ai编程
喵个咪4 小时前
GoWind Toolkit Go后端代码生成 完整全流程实战
后端·go·orm
杨充4 小时前
1.3 浮点型数据设计灵魂
开发语言·python·算法
basketball6165 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang