python进阶之路4.2---装饰器

装饰器

python中一切都是对象,对于函数来说也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也可以调用函数。

def test():
print("welcome to beijing")
test()

函数对象有一个name属性,可以拿到函数的名字:

test.__name__
>>test

如果,我们要增强函数test()函数的功能,比如,在函数前后自动打印日志,但又不希望修改test()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器(Decorator)”。

def log(func):
def wrapper(*args,**kw):
    print("where are you from?")
    return func(*args,**kw)
return wrapper
@log
#调用装饰器时,下面需要有函数
def test():
    print("welcome to beijing")
test()

观察上面的log,因为他是一个装饰器(decorator),所以接受一个函数作为参数,并返回一个函数。我们要借助Python@语法,把decorator置于函数定义处:

@log
def test():
    print("welcome to beijing")
test()

调用test函数,不仅会运行函数本身,还会运行装饰器里面的内容 把@log放到test()函数的定义处,相当于执行了语句:

test=log(test)

由于log()是一个decorator,返回一个函数,所以,原来的test()函数仍然存在,只是现在同名的test变量指向了新的函数,于是调用test()将执行新的函数,即log()函数中返回的wrapper()函数。 wrapper()函数的参数的定义是(args,*kw),因此,wrapper()函数可以接受任意参数的调用。在wrapper()函数内,首先打印日志,再紧接着调用原始函数。 如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,写出来会比较复杂。

如果说想在函数前后都需要添加相应的功能,比如一个页面函数前后添加登陆验证和打印信息,就需要用到三层嵌套,示例代码如下:

def Before(request,kargs):
    print ('before')
def After(request,kargs):
    print ('after')
def Filter(before_func,after_func):
    def outer(main_func):
        def wrapper(request,kargs):
            before_result = before_func(request,kargs)
            if(before_result != None):
                return before_result;
            main_result = main_func(request,kargs)
            if(main_result != None):
                return main_result;
            after_result = after_func(request,kargs)
            if(after_result != None):
                return after_result;

        return wrapper
    return outer

@Filter(Before, After)
def Index(request,kargs):
    print ('index')
Index('a','b')

下面先来说一下,三层代码的执行过程,原理和两层的是相同的。 1.依次将Before、After、Filter函数加载到内存中 2.加载装饰器 3.执行Filter()函数,加载outer()函数,返回return中的outer()函数,加载wrapper()函数,返回return中的wrapper()函数 4.执行Index()函数,并传入参数 5,执行wrapper()函数,

原文地址:https://www.cnblogs.com/lixingli/p/5165958.html