Python基础-44-装饰器详解

本文详细介绍了Python装饰器的作用,包括被装饰函数不带参数、带参数、带参数组的情况,还介绍了带参数装饰器、类装饰器的使用方法,最后探讨了多个装饰器的执行顺序,指出其是从里往外执行的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

装饰器的简单功能在前面已经有过介绍(装饰器基础),本篇详细介绍一下装饰器的作用

 

被装饰函数不带参数

代码部分:

# 在每个函数执行前打印出执行的函数名称
def print_log(func):
    def wrapper():
        print("当前执行的函数名为:",func.__name__)
        func()  
    return wrapper

@print_log
def send_word():
    print("正在执行send_word函数")

@print_log
def send_video():
    print("正在执行send_video函数")

send_word()
send_video()

执行结果:

 

被装饰函数带参数

代码部分:

# 操作的前提需要登录,必须输入正确的name和pwd才可以继续执行func
def login(func):
    def wrapper(name,pwd):
        if name == "admin" and pwd == "123456":
            print("登录成功,可以继续操作!!")
            func()  # 3.func()等同于send_word(),这里会执行send_word函数
        else:
            print("还未成功登录,不能操作")
    return wrapper

@login  # 1.这里相当于send_word=login(send_word);会去执行login函数,返回wrapper
def send_word():
    print("这是发布的内容")

# 2.send_word()等同于wrapper()此时会去执行wrapper函数;
# wrapper有两个必填函数,所以被装饰函数send_word()需要也需要传递两个参数
# 不传参数运行会报错wrapper() missing 2 required positional arguments: 'name' and 'pwd'
send_word("admin","123456")

 执行结果:

 

被装饰函数带参数组(常用)

带参数组,是因为不确定每个被装饰函数的参数个数,一般会用参数组来传参

在第一个demo的基础上优化一下

代码部分:

# 在每个函数执行前打印出执行的函数名称
def print_log(func):
    def wrapper(*args, **kwargs):
        print("当前执行的函数名为:",func.__name__)
        func(*args, **kwargs)
    return wrapper

@print_log
def send_word(*args, **kwargs):
    print("正在执行send_word函数,输出结果:{}",(args,kwargs))

@print_log
def send_video(*args, **kwargs):
    print("正在执行send_video函数,输出结果:",(args,kwargs))

send_word("suner","wang")
send_video(name="suner",age=20)

执行结果: 

 

带参数装饰器

上面的装饰器默认只能传递一个func参数,假设我们需要装饰器实现不同的装饰效果,可以在外层再封装一下

 

代码部分:

def print_log(category):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if category == "func_name":
                print("当前执行的函数名为:", func.__name__)
            elif category == "func_dir":
                print("当前执行的函数dir为:", func.__dir__)
            return func(*args,**kwargs)
        return wrapper
    return decorator


@print_log("func_name")  # 相当于@decorator
def send_word(*args, **kwargs):
    print("正在执行send_word函数,输出结果:",(args,kwargs))

@print_log("func_dir")   # 相当于@decorator
def send_video(*args, **kwargs):
    print("正在执行send_video函数,输出结果:",(args,kwargs))

send_word("suner","wang")
send_video(name="suner",age=20)

 

执行结果:

 

类装饰器

装饰器可以是一个函数,也可以是一个类

使用类装饰器主要依靠类的__call__方法,当使用 @ 形式将装饰器附加到函数上时,就会调用此方法。

代码部分:

class PrintLog():
    def __init__(self,func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("当前执行的函数名为:", self.func.__name__)
        self.func(*args, **kwargs)

@PrintLog
def send_word(*args, **kwargs):
    print("正在执行send_word函数,输出结果:",(args,kwargs))

send_word("suner",20)

 

执行结果:

 

多个装饰器的执行顺序

 

代码部分:

def decorator_001(func):
    print("-----001-----")
    def wrapper(*args,**kwargs):
        print("这是001装饰器")
        func(*args,**kwargs)
    return wrapper

def decorator_002(func):
    print("-----002-----")
    def wrapper(*args,**kwargs):
        print("这是002装饰器")
        func(*args,**kwargs)
    return wrapper

def decorator_003(func):
    print("-----003-----")
    def wrapper(*args,**kwargs):
        print("这是003装饰器")
        func(*args,**kwargs)
    return wrapper


@decorator_001
@decorator_002
@decorator_003
def send_word(*args, **kwargs):
    print("正在执行send_word函数,输出结果:",(args,kwargs))

send_word("suner",20)

执行结果:

由打印的003~001可以看出多个装饰器之间的执行顺序是从里往外执行的,至于为什么先打印001装饰器这里可能就涉及到底层的知识了,解释不来,我们只需要知道是按这样一个顺序执行的即可

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值