Python装饰器(&闭包)

   Python有一个强大的特性—装饰器,它可以给已经实现的代码块(函数)包裹上自己想要添加的功能,而不用考虑函数内是怎么实现的

阐述装饰器之前可以先了解一下Python另一个特性—闭包

闭包

闭包是在函数内再定义一个函数,并且提供了子函数需要的变量,这样可以把子函数与其用到的变量叫做闭包

def line_para(a, b):
    def line(x):
        return a * x + b
    return line

如上代码,定义一个line_para函数,其返回的是子函数line,line_para内定义函数line,这样实现了一个闭包,可以通过传入不同的参数a, b,来获得不同的数学上的二元一次函数

line1 = line_para(2, 4)
line2 = line_para(3, 6)
print(line1(10))
print(line2(10))
# 24
# 36

闭包可以根据需要,创建不同的,又具有一定相似度的函数。这种思想也是装饰器的思想

装饰器

上文有描述,装饰器可以给以实现的函数添加功能。这是一种优雅的实现方法,符合敏捷开发的封闭开放原则。

封闭开放原则:已经实现的功能代码不允许被修改,而是将其扩展

import time


def my_func(func):
    def inner(a)
        print(time.time())
        func(a)
        print(time.time())
    return inner
    

@my_func
def other_func(a):
    pass


other_func(123)

如上my_func就是实现一个简单的装饰器,假设函数other_func是从别人那儿拿来的,我们并不知道它是怎么实现的,只知道想要给他添加运行开始时间和结束时间。我们可以这样来理解它:

  1. 符号"@"标识程序会使用一个装饰器my_func,
  2. 程序将函数other_func作为参数传入装饰器my_func,之后又将返回值赋值给变量other_func
    other_func = my_func(other_fun)
  3. 然后将原函数other_function的参数传给装饰器my_function返回的对象
    my_func(other_func)(a)
  4. 这样再执行other_func就相当于执行装饰器my_func返回的对象inner函数,执行inner函数就会先打印一下时间戳,然后执行func函数,此时局部变量func指向的是原函数other_func的函数体,也就是执行原函数other_func,最后再打印一下时间戳,这样就实现了一个给原函数other_func添加显示开始、结束时间功能的装饰器

类装饰器

上面是用函数的方式实现装饰器,其实装饰器还可以通过类来实现

import time


class my_func:
    def __init__(self, func):
        self._func = func

    def __call__(self, *args, **kwargs):
        print(time.time())
        self._func(*args, **kwargs)
        print(time.time())


@my_func
def other_func(a)
    pass


other_func(123)

其运行的原理其实和函数实现方法差不多:

  1. 符号"@"标识程序会使用一个装饰器my_function
  2. 将函数other_func传给类my_func的实例,之后又将其返回值赋值给other_function
    other_func = my_func(other_func)
  3. 这样运行other_func就是运行类my_func的实例,参数就会被传入__call__方法中,执行call方法就可以实现打印开始时间戳,执行原函数other_func,打印结束时间戳

装饰器很强大,在Python中很多地方都用到它,比如Flask就是通过其实现了很多功能,有待我以后慢慢描述~~

猜你喜欢

转载自blog.csdn.net/weixin_40283460/article/details/82860868