一文搞懂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 小时前
10分钟搞懂 Rust 的 & 怎么用
后端
励志不掉头发的内向程序员3 小时前
从零开始的python学习——函数(2)
开发语言·python·学习
Gyoku Mint3 小时前
猫猫狐狐的“你今天有点怪怪的”侦察日记
人工智能·python·深度学习·神经网络·自然语言处理·pycharm·数据分析
DS小龙哥3 小时前
基于STM32设计的智能音乐练习辅助系统
后端
盼小辉丶3 小时前
PyTorch实战——GoogLeNet与Inception详解
pytorch·python·深度学习
梓羽玩Python3 小时前
AiPy 你的AI打工牛马来了!真正的开源Agent神器!
人工智能·python·github
_風箏3 小时前
SpringBoot【集成p6spy】使用p6spy-spring-boot-starter集成p6spy监控数据库(配置方法举例)
后端
_風箏3 小时前
SpringBoot【集成Druid】监控数据库报错 Failed to bind properties under ‘‘ to javax.sql.DataS
后端
shepherd1113 小时前
深入解析Flowable工作流引擎:从原理到实践
java·后端·工作流引擎