Loading

python装饰器

在python中所有东西都是对象,都是object,函数也不例外
装饰器本身就是一个可调用的函数,装饰器也叫语法糖,在闭包的基础上实现
装饰器的作用:不影响原因函数的功能,还能添加新的功能
 
 
装饰器语法
#定义装饰器函数
def decorator():
    ...
    
    
@decorator #使用@加装饰器函数名,给my_func使用decorator装饰器
def my_func():
    ...
 
假设我们有一个A函数,我们要在函数执行前输出start,函数结束执行时输出end
如果不使用装饰器在函数内直接输出
def a_func():
    print('start')
    v = (1, 2, 3,)
    print('end')
    return v
使用装饰器实现
def func1(func):  # 外部闭包函数的参数是被装饰的函数对象
    def func2():
        print('start')
        res = func()  # 外部函数接收的参数,被装饰函数的调用
        print(res)
        print('end')
        return res

    return func2


@func1
def a_func():
    v = (1, 2, 3,)
    return v


a_func()
'''
执行流程:
相当于 func1(a_func)() 把a_func传递给func1再调用一下
1.func1将被装饰的函数当做参数传递过去
2.func1 返回了func2对象
3.func2对象内部 print start
4.实例func() 相当于实例a_func()调用
5.打印实例结果及end,再将res返回给func2
最终fucn1返回func2的返回值也就是res == a_func()
          
'''
携带参数的装饰器
def arg_func(sex):  # sex 要传递的参数
    def func1(base_func):  # 被装饰的函数
        def func2():
            if sex == 'man':
                print('this is boy')
            if sex == 'woman':
                print('this is girl')
            base_func()  # 执行被装饰的函数

        return func2  # 将func2返回到func1

    return func1  # 将func1 返回给arf_func


@arg_func(sex='man')  # 传递的参数
def man():
    print('man')


@arg_func(sex='woman')
def woman():
    print('woman')
    
    
'''
执行流程
arg_func(sex='woman')(base_func)()
1.调用arg_func(sex=''man),内部返回了func1
2.fucn1携带被装饰的函数对象参数,返回了func
3.func内部处理逻辑和被装饰函数

'''
 
被装饰的函数携带参数
只需要在最内部函数传入参数即可
def func1(func): #外层函数接收被装饰的函数对象
    def func2(x, y): # 内层函数接收被装饰的函数参数
        x += 5
        y += 5
        return func(x, y) #调用被装饰函数,并且传参

    return func2 #返回func2


@func1
def my_sum(a, b):
    print(a + b)


my_sum(1, 2) #13
'''
虽然参数传递的是是1和2
但是经过func2()的时候 在内部进行了加法
最终到了fucn调用的时候传入的就是加过的值
'''
functools.wraps
装饰器在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变)
为了不影响,Python的functools包中提供了一个叫wraps的decorator来消除这样的副作用,如果要保留原有函数的名称和函数属性,可以使用对应方法
'''不使用functools'''
def func1(func):
    def func2(x, y):
        '''in func2'''
        return func(x, y)

    return func2


@func1
def my_sum(a, b):
    '''in sum'''
    print(a + b)


print(my_sum.__name__) # func2
print(my_sum.__doc__) # in func2
'''使用functools'''
#导包
import functools


def func1(func):
     # 参数传入不被影响的被装饰函数,
     # 操作相当于 func2.__name__ = my_sum.__name__
    @functools.wraps(func) 
    def func2(x, y):
        '''in func2'''
        return func(x, y)

    return func2


@func1
def my_sum(a, b):
    '''in sum'''
    print(a + b)


print(my_sum.__name__)  # my_sum
print(my_sum.__doc__)  # in sum

 

posted @ 2022-08-25 17:40  木子七  阅读(40)  评论(0编辑  收藏  举报