自学Python--装饰器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_41402059/article/details/82319749

背景:

不想改变函数的调用方式但是想在原函数前后添加功能

通过闭包实现(初级实现装饰器):

下面f1()是被装饰的函数,f2()是装饰器函数

def f1():
    print('this is f1')

def f2(f):
    print('this is f2')
    def inner():
        print('this is inner')
        f()
    return inner

f1 = f2(f1)
f1() # f1原功能输出 this is f1不变,在f1前面输出this is f2 和 this is inner
'''
this is f2
this is inner
this is f1
'''

开放封闭原则:

开放:对扩展是开放的

封闭:对修改是封闭的

语法糖:

使代码更便捷 ’@‘

先调用@修饰的函数再调用被修饰函数

被修饰的函数的返回值无法正常接收,需要在装饰器函数里获取被装饰函数的返回值再返回

上面的例子使用语法糖后:

def f2(f):
    print('this is f2')
    def inner():
        print('this is inner')
        f()
    return inner

@f2
def f1():
    print('this is f1')
    return 'f1 return'

f1()
'''
this is f2
this is inner
this is f1
'''
res = f1()
print(res) # None


================================
# 获取被装饰函数的返回值
def f2(f):
    print('this is f2')
    def inner():
        print('this is inner')
        res = f()
        return res
    return inner

@f2
def f1():
    return ('this is f1')

print(f1())
'''
this is f2
this is inner
this is f1
'''

动态传参的装饰器:

def f1(f):
    def inner(*args, **kwargs):
        print('this is inner')
        res = f(*args, **kwargs)
        return res
    return inner

@f1
def f2(a, b):
    return [a, b]

@f1
def f3(a, b, name='test'):
    return [a, b, {'name':name}]

res2 = f2(1, 2)
print(res2) # this is inner [1, 2]

res3 = f3(1, 2, 'xinian')
print(res3) # this is inner [1, 2, {'name': 'xinian'}]

装饰器固定模式:

def wrapper(func):
    def inner(*args, **kwargs):
        res = func(*args, **kwargs)
        return res
    return inner

@wrapper
def test(a, b):
    return a + b

res = test(1, 2)
print(res) # 3

多个装饰器:

def wrapper1(f): # f = inner2
    def inner1():
        print('inner1 before f')
        f()
        print('inner1 after f')
    return inner1

def wrapper2(f): # f = test
    def inner2():
        print('inner2 before f')
        f()
        print('inner2 after f')
    return inner2

@wrapper1  # 然后关联第二个,此时wrapper1的入参f是前面wrapper2返回的inner2,返回inner1
@wrapper2  # 先关联最近的,此时wrapper2的入参f = test,返回inner2
def test():
    print('this is test')

'''
下面调用时相当于调用inner1,
先输出inner1 before f
然后调用inner1里面的f(),此时f = inner2
因此输出inner2 before f
然后inner2里面的f(),此时f = test
因此执行真正的test,输出this is test
然后输出inner2 after f,执行完inner2回到调用点inner1
输出inner1 after f
'''
test()
'''
先执行wrapper1在调用test前的代码,
再执行wrapper2在调用test前的代码,
再执行test,
再执行wrapper2在调用test后的代码,
再执行wrapper1在调用test后的代码,
inner1 before f
inner2 before f
this is test
inner2 after f
inner1 after f
'''

猜你喜欢

转载自blog.csdn.net/weixin_41402059/article/details/82319749