彩虹然

rainbow-ran

Python3.7之装饰器

一、装饰器的功能

针对软件开发的“开放-封闭”原则,即:

封闭:已实现的功能代码块不应该被修改

开放:对现有功能的扩展开放

所谓的装饰器,就是通过装饰器函数,来修改原函数的一些功能,使得原函数不需要修改。

二、装饰器引入

1.原有的功能函数如下:

def f1():
    print('f1 called: ')


def f2():
    print('f2 called: ')

2.现需要对两个功能函数进行权限验证,即需要引入一个闭包函数:

def w1(func):
    def inner():
        print('----权限验证----')
        func()

    return inner

review:闭包函数的条件

① 在一个外函数中定义了一个内函数。

② 内函数里运用了外函数的临时变量。

③ 并且外函数的返回值是内函数的引用。

3.装饰后的代码:

# 在执行w1函数的时候,此时直接把inner函数返回了,同时把它赋值给f1
# 此时的f1已经不是未加装饰时的f1了,而是指向了w1.inner函数地址
def w1(func):
    def inner():
        print('----权限验证----')
        func()

    return inner

# 当python解释器执行到这句话的时候,会去调用w1函数,同时将被装饰的函数名作为参数传入(此时为f1)
@w1  # f1 = w1(f1)
def f1():
    print('f1 called: ')


@w1
def f2():
    print('f2 called: ')

# 在调用f1()的时候,其实调用的是w1.inner函数
# 那么此时就会先执行权限验证,然后再调用原来的f1(),该处的f1就是通过装饰传进来的参数f1
f1()
f2()

'''
----权限验证----
f1 called: 
----权限验证----
f2 called: 
'''

这样下来,就完成了对f1的装饰,实现了权限验证。

三、对有参函数进行装饰

如果原函数有参数,那闭包函数必须保持参数个数一致,并且将参数传递给原方法

1.固定参数:

def w_say(fun):

    def inner(name):  # 此处应有参数
        """
        如果被装饰的函数有形参,那么闭包函数必须有参数
        :param name:
        :return:
        """
        print('say inner called')
        fun(name)  # 将参数传给原方法

    return inner


@w_say
def hello(name):
    print('hello ' + name)


hello('Vivian')
'''
say inner called
hello Vivian
'''

2.非固定参数:

def w_add(func):

    def inner(*args):
        print('add inner called')
        func(*args)

    return inner


@w_add  # 共有装饰器,被装饰的函数的形参不固定
def add(a, b):  # 被装饰的函数有形参
    print('%d + %d = %d' % (a, b, a + b))


@w_add
def add2(a, b, c):
    print('%d + %d + %d = %d' % (a, b, c, a + b + c))


add(2, 4)
add2(2, 4, 6)

'''
add inner called
2 + 4 = 6
add inner called
2 + 4 + 6 = 12
'''

四、对带有返回值的函数进行装饰

def w_test(func):
    def inner():
        print('w_test inner called start')
        # 对test进行调用之后,接收返回值s
        str0 = func()  # 原test的返回值传递给str0
        print('w_test inner called end')
        # 被装饰之后的test返回值为str0
        return str0
    return inner


@w_test  # test = w_test(test)
def test():
    print('this is test fun')
    return 'hello'


ret = test()
print('ret value is %s' % ret)

'''
w_test inner called start
this is test fun
w_test inner called end
ret value is hello
'''

五、带参数的装饰器

posted @ 2020-01-16 16:27  彩虹然  阅读(347)  评论(0编辑  收藏  举报