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

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


相关推荐
Moonbit11 小时前
MoonBit Pearls Vol.9:正则表达式引擎的两种实现方法:导数与 Thompson 虚拟机
后端·正则表达式·编程语言
用户7851278147011 小时前
淘宝获取商品详情数据API接口PC端和App端的实际操作指南
python
神仙别闹11 小时前
基于 Python 模式识别(纹理图片里的目标检测)
python·目标检测·目标跟踪
文心快码BaiduComate12 小时前
一人即团队,SubAgent引爆开发者新范式
前端·后端·程序员
小小测试开发12 小时前
用Playwright实现接口自动化测试:从基础到实战
python·自动化·接口自动化·playwright
掘金一周12 小时前
2025年还有前端不会Nodejs ?| 掘金一周 9.25
android·前端·后端
RoyLin12 小时前
前端·后端·node.js
泉城老铁12 小时前
springboot常用的注解需要了解,开发必备
spring boot·后端
hhcgchpspk12 小时前
flask获取ip地址各种方法
python·tcp/ip·flask
RoyLin13 小时前
C++ 基础与核心概念
前端·后端·node.js