Python函数装饰器(functional decorators)就是拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能。

       这个函数的特殊之处在于它的返回值也是一个函数,这个函数是内嵌“原”函数的函数。

       例如写一个打印hello的函数,如下

def hello():               
    print('hello')

if __name__=='__main__':    
    hello()

       输出结果如下:

 

Python 获取key PYTHON 获取函数的装饰器名称_Python

       如果我们要修改函数内容,对函数进行监控,可以直接修改代码。但往往由于工作量很大,不可能一个一个改。所以要将其独立出来进行拓展。在Java里面称为注解,在Python中称为装饰器。

       装饰器就是给原来的函数加了一个包装(wrapper),利用包装对原函数进行修改与装饰,从而达到拓展功能的目的。

       在这里我们增加一个简单的装饰器:

def log(func):       #装饰器核心
    def wrapper():   #定义具体装饰过程
        print('before calling', func.__name__)
        func()
        print('end calling', func.__name__)
    return wrapper

@log                       
def hello():               #增加装饰器,func相当于一个函数指针
    print('hello')

if __name__=='__main__':    #主函数
    hello()                 #相当于调用log(hello())

       其输出结果如下:

Python 获取key PYTHON 获取函数的装饰器名称_Python_02

 

       如果带参数怎么办呢?带参数可以如下处理

def log(func):       #装饰器核心
    def wrapper(name):   #定义具体装饰过程
        print('before calling', func.__name__)
        func(name)
        print('end calling', func.__name__)
    return wrapper

@log                       
def hello(name):               
    print('hello',name)

if __name__=='__main__':    #主函数
    hello('CSDN')

       输出结果如下

Python 获取key PYTHON 获取函数的装饰器名称_装饰器_03

 

       因为参数有很多,所以我们也可以用Python中的通用参数表示。

       一个*表示无名字参数,两个**表示有名字参数,即:

       *args:无名字参数

       **kvargs:有名字参数(有名字无名字就是有没有参数名)

       代码就可以改写为如下,增加年龄:

def log(func):       #装饰器核心
    def wrapper(*args,**kvargs):   #定义具体装饰过程
        '''
        #args为无名字参数
        ##kvargs为有名字参数
        '''
        print('before calling', func.__name__)
        print('args:',args,'kvargs:',kvargs)
        func(*args,**kvargs)
        print('end calling', func.__name__)
    return wrapper

@log                       
def hello(name,age):            
    print('hello',name,age)

if __name__=='__main__':    #主函数
    #hello('CSDN',2)
    hello(name='CSDN',age=2)

       运行结果如下:

Python 获取key PYTHON 获取函数的装饰器名称_主函数_04

 

       我们发现kvargs为空。说明CSDN和2都是无名字的变量,如果将


  


hello('CSDN',2)

       改为

hello(name='CSDN',age=2)

       再次打印结果如下:

Python 获取key PYTHON 获取函数的装饰器名称_主函数_05

 

       这个时候CSDN和2就变成了有名字的变量。

       再进阶一下,在写装饰器的时候log(可以定义其他的)是分等级的,也就是说其可以带参数,这个时候代码思想都是一致的,就是再在装饰器内加一层即可。

def log(level,*args,**kvargs):     #装饰器核心
    def inner(func):                     #嵌套两层
        def wrapper(*args,**kvargs):   #定义具体装饰过程
            print(level,'before calling', func.__name__)
            print(level,'args:',args,'kvargs:',kvargs)
            func(*args,**kvargs)
            print(level,'end calling', func.__name__)
        return wrapper
    return inner

@log(level='INFO')                      
def hello(name,age):              
    print('hello',name,age)

if __name__=='__main__':    #主函数
    #hello('CSDN',2)
    hello(name='CSDN',age=2)

       结果如下:

Python 获取key PYTHON 获取函数的装饰器名称_Python_06

 

       唠唠叨叨说了一点,最后提炼一下,装饰器大体思路如下:

def myDecorator(...):    #定义装饰器,可能带参数
    def decorator(func):    #装饰器核心,以被装饰的函数对象为参数,返回装饰后的函数对象
        def wrapper(*args, **kvargs):    #装饰的过程,参数列表适应不同参数的函数
            ...    #修改函数调用前的行为
            func(*args, **kvargs)    #调用函数
            ...    #修改函数调用后的行为
        return wrapper
    return decorator

@myDecorator(...):    
def myFunc(...):      #给函数加上装饰器,自己定义的功能函数

if __name__=='__main__':  #主函数

       欢迎交流!