Python进阶(四):浅析装饰器(decorator)@ - Go语言中文社区

Python进阶(四):浅析装饰器(decorator)@


之前在看代码的时候看见有些代码会在函数前面用一个@+函数名修饰,开始有点困惑的。遂查找各种资料,才知道这是python的一种语法糖。虽然理解起来有点困难,可是理解过后就会佩服python的简洁性。

装饰器@

一.介绍

函数就是我们的衣服,单个函数就比如一件短袖衬衫。编程就是不断的调用不同的函数,就比我们身上穿不同的衣服。当天气变凉的时候我们就必须加外套了,相同的我们需要对某个函数进行某种操作(并且并不想改变这个函数的内部结构)的时候,装饰器就派上了用场。比如我们想知道一个函数完整的执行时间,那么我们可以编写另一个函数B,然后将函数A传递进去,在B的内部计算函数A的执行时间。编写函数B的好处就是下次还要用到的使用就可以直接调用了。但是如果我们在写函数A的时候就想实现计算这个函数A的执行时间(就是每次调用的时候都会计算执行时间),那有什么办法呢?这是@装饰器就起作用了,而且可以很简洁的表示出来

def B():
    pass

@B
def A():
    pass
'''
上面的代码相当于
A=B(A)
'''

二.通过代码来理解

1.函数的调用

函数在python中是可以作为变量,或者说作为实参传入一个函数的:

def func1(func):
    print("Start func1")
    func()
    print("End func1")

def func2():
    print("Start func2")
    print("End func2")

func1(func2)

结果:结果

2.函数的嵌套

这一步,我们在升级一下。加一个函数的嵌套,说白了就是在一个函数中定义一个新的函数。

def func1(func):
    print("This is func1")
    def insidefunc():
        print("This is the inside function")
        func()
        print("Inside function end")
    print("func1 endn")
    return insidefunc

def func2():
    print("This func2")
    print("func2 endn")

print("start:")
print("func2 name:", func2.__name__, "n")

print("To decorate:")
func2 = func1(func2)

print("end:")
print("func2 name", func2.__name__, "n")
func2()

能够理解以上代码,其实就基本理解装饰器了
他主要就是将func2变成另一个函数而已。
执行结果:
这里写图片描述

3.运用装饰器

好了我们开始运用装饰器吧

def func1(func):
    print("This is func1")
    def insidefunc():
        print("This is inside function")
        func()
        print("Inside function end")
    print("func1 endn")
    return insidefunc

@func1
def func2():
    print("This is func2")
    print("func2 end")

print("start:")
print("func2 name:", func2.__name__)

func2()

我们先来看一下执行效果:
这里写图片描述
从结果可以看到,当我们在修饰时,就已经调用好了修饰函数func1修饰了,之后在调用的时候就不在调用修饰函数func1了。这里要注意的是,我们在定义修饰函数时必须在内部定一个新的函数insidefunc,然后在这个新的函数中进行操作后,最后返回这个insidefunc,也就是说func2已经变成了insidefunc了

4.被修饰的函数传入参数

当然,我们的被修饰函数是可以传入函数的。只不过我们需要在修饰函数的内部函数insidefunc的()的参数与被修饰函数的参数数量一致就好。

def func1(func):
    print("This is func1")
    def insidefunc(a, b):
        print("This inside function")
        a = func(a, b)
        print("Parameter from func:", a)
        print("Inside function end")
    print("func1 endn")
    return insidefunc

@func1
def func2(a, b):
    print("This is func2")
    print("func2 end")
    return a + b

print("start")
func2(4, 5)

这里写图片描述

5.修饰函数传入参数

我们的修饰函数也是可以传入参数的

def func1(arg=True):
    if arg:
        def _func1(func):
            print("This in _func1")
            def insidefunc(a, b):
                print("This is in _func1.insidefunc")
                c = func(a, b)
                return c
            return insidefunc
        return _func1
    else:
        def _wfunc1(func):
            print("This is _wfunc1")
            return func
        return _wfunc1

@func1(True)
def func2(a, b):
    print("This func2")
    return a + b

@func1(False)
def func3(a, b):
    print("This is func3")
    return a * b

print(func2(4, 5))
print("n")
print(func3(4, 5))

这里写图片描述

6.装饰器的连续套用

def func1(func):
    def _func1(a):
        print("This is _func1")
        a = func(a)
        return a * a
    return _func1

def func2(func):
    def _func2(a):
        print("This is _func2")
        a = func(a)
        return a * 3
    return _func2

@func1
@func2
def func3(a):
    print("This is func3")
    return a

print("Start:")
print(func3(1))
print(func3(2))

这里写图片描述


还有一些其他装饰器的用法,比如在类里面装饰函数,或者用类来装饰就不一一展开了

三.装饰器的主要用途

说了这么多,大家可能对装饰器到底在实际开发中有什么应用还是很困惑的。其实在实际的开发中,装饰器还是很常见的,而且用处还很大。
主要应用于几个方面:参数检查、统计时间、缓存、注册回调函数、函数加日志 、线程异步等等
举个例子多线程异步:

from threading import Thread
from functools import wraps


def async(func):
    @wraps(func)
    def async_func(*args, **kwargs):
        func_hl = Thread(target=func, args=args, kwargs=kwargs)
        func_hl.start()
        return func_hl

    return async_func


if __name__ == '__main__':
    from time import sleep


    @async
    def print_somedata():
        print('starting print_somedata')
        sleep(2)
        print('print_somedata: 2 sec passed')
        sleep(2)
        print('print_somedata: 2 sec passed')
        sleep(2)
        print('finished print_somedata')


    @async
    def _print_somedata():
        print('starting _print_somedata')
        sleep(2)
        print('_print_somedata: 2 sec passed')
        sleep(2)
        print('_print_somedata: 2 sec passed')
        sleep(2)
        print('finished _print_somedata')


    def main():
        print_somedata()
        print('back in main')
        _print_somedata()
        print('back in main')


    main()

这里写图片描述

详细用途可以看看官方文档:https://wiki.python.org/moin/PythonDecoratorLibrary


好了,今天就到这。谢谢浏览。
有问题探讨加QQ:1043601529。

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_37720172/article/details/78266260
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-06-13 20:07:25
  • 阅读 ( 546 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢