zoukankan      html  css  js  c++  java
  • 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()函数,

  • 相关阅读:
    今天看到的一些好文语句摘录
    laravel5 怎么获取数组形式的数据
    laravel5.4将excel表格中的信息导入到数据库中
    phpmax_execution_time
    laravel 5.4 导出excel表格
    使用php函数ini_set()重新设置某个配置的设置值
    艾伟_转载:VS.NET 2010 新功能 [整理] 狼人:
    艾伟_转载:[一步一步MVC]第五回:让TagBuilder丰富你的HtmlHelper 狼人:
    艾伟_转载:.NET 4.0中数组的新增功能 狼人:
    艾伟_转载:一个简单的 Generic Factory 类 狼人:
  • 原文地址:https://www.cnblogs.com/lixingli/p/5165958.html
Copyright © 2011-2022 走看看