python装饰器的一点理解

本文全面解析Python装饰器的应用,包括单一装饰器、多重装饰、多装饰器应用、带参数的装饰器、不定参数装饰器、装饰器带参数、类装饰器及functools.wraps的使用。通过实例展示如何在不修改原始函数的基础上增加额外功能。

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

内容:
装饰器,一装饰多,多装饰一,多装饰多,函数带参数,不定参数,装饰器带参数,类装饰器,functools.wraps。

装饰器感觉就是在不改变原代码的情况给它新添一些功能之类的。

1.装饰器
丢出装饰器长相

def aaa(func):
    print("aaa")
    def bbb():
        print("bbb")
        func()
    return bbb

@aaa
def test():
    print("test")

test()

输出结果是

aaa
bbb
test

原来的函数 test(),会输出一个"test",现在在原基础上,多输出了一点东西。

其中没见过的也就一个@aaa
这个语法糖的效果大概等同于先将test定义后再加一句test=aaa(test)
执行aaa(test),定义一个bbb函数并将这个函数作为返回值赋给test
来达到效果,使得之后调用test的时候会调用到装饰器内部定义的函数bbb,同时bbb内也能通过参数func调用到原函数test

……………………………………………………………………………………………………………………………………………………

2.一个装饰器能够装饰多个函数

def aaa(func):
    print("aaa")
    def bbb():
        print("bbb")
        func()
    return bbb

@aaa
def test():
    print("test")

@aaa
def test2():
    print("test2")

test()
test2()

输出:

aaa
aaa
bbb
test
bbb
test2

理解到了装饰器,这个也不难理解。定义的时候便执行了两次aaa,调用两个函数也调用了两次bbb只是参数func不同。

……………………………………………………………………………………………………………………………………………………
3.多个装饰器来装饰一个函数。

def aaa(func):
    print("aaa")
    def bbb():
        print("bbb")
        func()
    return bbb

def ccc(func):
    print("ccc")
    def ddd():
        print("ddd")
        func()
    return ddd
    
@aaa
@ccc
def test():
    print("test")

test()

输出

ccc
aaa
bbb
ddd
test

很多解释是装饰器是从下往上执行的,这是结果。

深入理解一点,
这里@aaa理当装饰的是
@ccc装饰了的test
这一整体

@aaa
@ccc
def test

这种形式大致也可以改为在定义完函数后会再加一句test=aaa(ccc(test))
这就不难理解为什么会先输出ccc后输出aaa
……………………………………………………………………………………………………………………………………………………
4.多个装饰器装饰多个函数

感觉是废话。
……………………………………………………………………………………………………………………………………………………

5.装饰带参数的函数

def aaa(func):
    print("aaa")
    def bbb(n):
        print("bbb")
        func(n)
    return bbb

@aaa
def test(n):
    print(n)
    print("test")


test(5)

输出

aaa
bbb
5
test

test里带了什么参数,bbb也就也接受个什么参数就行,调用func也记得把参数带上就行。
……………………………………………………………………………………………………………………………………………………
6.带不定参数
在一个装饰器修饰多个函数的时候,各个函数的参数不同,那就可以用不定参数。

def aaa(func):
    print("aaa")
    def bbb(*args):
        print("bbb")
        func(*args)
    return bbb

@aaa
def test(n):
    print(n)
    print("test")
@aaa
def test2(x,y):
    print(x+y)
    print("test2")

test(5)
test2(3,4)

输出

aaa
aaa
bbb
5
test
bbb
7
test2

还有bbb(*args,**kwargs)
*args 表示多个无名参数,他是一个tuple
**kwargs 表示多个带关键字参数,是个dict
需要什么用什么就行,同时用需要*args在前面。
……………………………………………………………………………………………………………………………………………………
7.装饰器带参数
效果如下

def ccc(flag):
    def aaa(func):
        print("aaa")
        def bbb():
            if flag:
                print("11111")
            else:
                print("22222")
            func()
        return bbb
    return aaa

@ccc(True)
def test1():
    print("test1")

@ccc(False)
def test2():
    print("test2")

test1()
test2()

输出:

aaa
aaa
11111
test1
22222
test2

这种情况的时候用这个能少写一段代码hh
……………………………………………………………………………………………………………………………………………………
8.类装饰器
和普通的函数的装饰器有一点点区别,本质上还是就那样。
样子大概是

class aaa(object):
    def __init__(self,func):
        print("aaa")
        self.__func=func

    def __call__(self):
        print("bbb")
        self.__func()

@aaa
def test():
    print("test")

test()

输出:

aaa
bbb
test

类装饰器的时候 @aaa也还是相当于在定义完test后加一句test=aaa(test),毕竟在python里万物皆对象。
定义aaa的一个对象test,执行构造方法,将原函数test作为参数func带入,并赋给类中的__func
之后在执行test()的时候便会等同于执行test.__call__(),达到之前装饰器效果。
类装饰器会更灵活一些,封装性也更好。
……………………………………………………………………………………………………………………………………………………
9.functools
装饰器有个缺点,原函数的元信息不见了。
如下:

def aaa(func):
    print("aaa")
    def bbb():
        print("bbb")
        func()
    return bbb

@aaa
def test():
    print("test")

test()
print(test.__name__)

输出

aaa
bbb
test
bbb

毕竟test已经被我们覆盖掉了。
所以functools模块
提供了一个装饰器@functools.wraps
如下:

import functools

def aaa(func):
    print("aaa")
    @functools.wraps(func)
    def bbb():
        print("bbb")
        func()
    return bbb

@aaa
def test():
    print("test")

test()
print(test.__name__)

输出:

aaa
bbb
test
test

用这个装饰器再来修饰bbb便能解决之前的问题。


以上便是我对装饰器的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值