python 装饰器理解

简介

装饰器可以在不修改原有代码的基础上添加新的功能,可以将重复重用的代码抽取出来,进一步解耦,方便维护,一般适用于插入日志、性能测试、事务处理、缓存等

装饰器的前提

闭包

一般来说,当一个函数嵌套另一个函数时,内部函数引用到了外部函数的变量,则形成了闭包,如下所示,outter与inner形成了闭包

def outter():
    n = 1
    def inner():
        print(n)
        return n
    return inner()

print(outter())

闭包的作用

1.内部函数可以访问外部函数的变量
2.将外层变量持久化到内存中(一般来说,函数内部的局部变量在这个函数运行完以后,就会被Python的垃圾回收机制从内存中清除掉)

装饰器的实现方式

方法装饰器

直接创建

def outter(func):
    def inner(*args, **kwargs):
        '''inner'''
        print('inner start')
        return func(*args, **kwargs)
    return inner

@outter
def decorator():
    '''decorator'''
    print('decorator')

decorator()
print(decorator.__name__)
print(decorator.__doc__)

image

由此结果发现,当添加装饰器后会改变原有函数的__name__及__doc__属性,为此我们需要纠正回来

修改函数的名及注释

使用functools下的wraps转译

from functools import wraps

def outter(func):
   @wraps(func)
   def inner(*args, **kwargs):
       '''inner'''
       print('inner start')
       return func(*args, **kwargs)
   return inner

@outter
def decorator():
   '''decorator'''
   print('decorator')

decorator()
print(decorator.__name__)
print(decorator.__doc__)

image

可传参的装饰器

需要在外层再包装一个函数,传入需要传递的参数即可,传入的参数也可以用于内部逻辑代码的处理

from functools import wraps

def decorator(name):
    def outter(func):
        @wraps(func)
        def inner(*args, **kwargs):
            '''inner'''
            print(f'name:{name}')
            print('inner start')
            return func(*args, **kwargs)
        return inner
    return outter

@decorator(name='test')
def test():
    print('test')

test()

image

类装饰器

直接创建(不带参数)

类装饰器不携带参数,只需构造方法传入方法,重写__call__方法即可

class Decorator():

    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print('Decorator start')
        self.func(*args, **kwargs)
        print('Decorator finish')

@Decorator
def test():
    print('test')

test()

image

携带参数创建

对于携带参数的类装饰器,构造方法需要为参数, 需要重写__call__方法且需要添加内部函数并返回,__call__方法传入方法,内部函数传递被装饰的函数的参数

class Decorator():

    def __init__(self, name):
        self.name = name
    
    def __call__(self, func):
        def inner(*args, **kwargs):
            print('inner start')
            print(self.name)
            func(*args, **kwargs)
            print('inner finish')
        return inner

@Decorator(name='test')
def test():
    print('test')

test()

image

posted @ 2022-05-27 17:42  形同陌路love  阅读(61)  评论(0编辑  收藏  举报