牛叔叔 的笔记

好好学习

2020-12-22 15:51

最通俗易懂简洁的告诉你Python中的@修饰符(装饰器)如何定义

牛叔叔

Python

(1961)

(0)

收藏

@在Python中可以用来修饰函数或者类,但是更多的是修饰函数,用来在不改变即有函数代码的情况下,给函数增加新的功能。(或者类)

比如我们在使用Flask开发web应用的时候,在方法前就使用@app.route('/wanmait')来给方法添加web请求路由映射。

如何创建自己的@修饰符呢?

首页@修饰符就是函数

我们把用@修饰符 修饰的函数叫做被修饰函数

比如有个函数:

def wanmait_fun1():
    print("在万码学堂学习编程")
def wanmait_fun2():
    print("在万码学堂学习Python")

wanmait_fun1()
wanmait_fun2()

执行结果为:

在万码学堂学习编程
在万码学堂学习Python

现在我们想自己定义个修饰符,来修饰这两个函数,以改变一点什么。

现在我们定义一个最简单的符合修饰符要求的函数如下:

def test(func):
    def wrapper():
        print("wanmait.com test...")
    return wrapper

@test
def wanmait_fun1():
    print("在万码学堂学习编程")
@test
def wanmait_fun2():
    print("在万码学堂学习Python")

wanmait_fun1()
wanmait_fun2()

执行结果:

wanmait.com test...
wanmait.com test...

注意这个test()函数的参数func,实际在@后的修饰符就是要调用执行的函数,并且会将被修饰函数传递给这个修饰函数,所以要求这个修饰符函数必须要接受一个函数参数。我们的目标是这个参数应该传递进来一个函数对象。(Python中函数也是对象,可以传递。)

这个函数的返回值必须也是一个函数(在这个函数内部定义的函数),这个返回的函数就是最终使用修饰符之后执行的函数。

所以上面的代码使用@test修饰后,实际执行的是test函数中定义的wrapper函数。

我们当然不希望这样,我们希望还是要执行(当然执不执行也还是由程序逻辑来决定)被修饰函数并且正确的接受所有参数,那如何处理呢?

我们只要在wrapper函数定义上允许任何参数传入即可,使用可变参数和可变关键字参数。

def goto_wanmait(func):
    def wrapper(*args,**kwargs):
        print("现在就去万码学堂!")
        func(*args,**kwargs)
        print("在wanmait.com学习很快乐!")
    return wrapper

这个函数的返回值是一个函数(在这个函数内部定义的函数),这个函数可以接受任意参数(无参,可变参数、可变关键字参数)

func(*args,**kwargs)

这样代码确定了调用传递进来的函数(也就是被修饰函数),而且将任意参数解构传递进去(这种形态保证了一定符合被修饰函数的参数定义)

从而完成了@修饰符这件事的逻辑。

@goto_wanmait
def wanmait_fun1():
    print("在万码学堂学习编程")
@goto_wanmait
def wanmait_fun2():
    print("在万码学堂学习Python")
    
wanmait_fun1()
wanmait_fun2()

执行结果:

现在就去万码学堂!
在万码学堂学习编程
在wanmait.com学习很快乐!
现在就去万码学堂!
在万码学堂学习Python
在wanmait.com学习很快乐!

到这里我们顺利定义了我们自己的修饰符,假如想要给修饰符传递参数怎么办呢?

那就只要再增加一层来接受参数调用即可,注意这时候@修饰符后加了()和参数来使用修饰符,实际上这时候是调用了这个修饰符函数,要求返回的结果必须是刚才我们所描述的形式(就是能接受一个func函数作为参数并返回一个函数来执行),代码如下:

def goto_wanmait(name='无名'):
    def wrapperoutter(func):
        def wrapper(*args,**kwargs):
            print(f"【{name}】现在就去万码学堂!")
            func(*args,**kwargs)
            print(f"【{name}】在wanmait.com学习很快乐!")
        return wrapper
    return wrapperoutter

@goto_wanmait(name="小明")
def wanmait_fun1():
    print("在万码学堂学习编程")
@goto_wanmait(name="小红")
def wanmait_fun2():
    print("在万码学堂学习Python")

wanmait_fun1()
wanmait_fun2()

运行结果:

【小明】现在就去万码学堂!
在万码学堂学习编程
【小明】在wanmait.com学习很快乐!
【小红】现在就去万码学堂!
在万码学堂学习Python
【小红】在wanmait.com学习很快乐!

这就是Python中的修饰符定义,很简洁又很实用的Python装饰器。

0条评论

点击登录参与评论