zoukankan      html  css  js  c++  java
  • python 装饰器

    装饰器语法

    定义一个函数 

    # -*-coding:utf-8 -*- 
    def  foo():                #定义一个foo的函数 
        print  "foo"        #打印输出
    foo()                      #调用foo函数 这样子函数才会执行
    foo                        #返回一个函数的内存地址,所以是可以被当做参数来传参 

    详解下面函数的执行过程

    # -*-coding:utf-8 -*- 
    def   f1(arg): 
        arg()
     
    def   func():
        print "I am func" 
    f1(func)             #调用func函数返回的内存地址

    执行过程: 

    1 python是顺序执行,加载f1函数到内存
    2 加载func函数到内存
    3 调用f1函数,开始执行
    4 把func传递给f1函数 此时呢 arg = func
    5 由此执行f1函数里面的内容func()
    6 由于条用了func(),所以开始执行func函数
    7 由此执行func函数里面的内容,打印 “i am func” 

     如图:

     
    目前有基础平台和业务平台,业务平台调用基础平台的代码接口
    有这样的一个需求,需要给基础平台所有代码接口加一个用户验证
    的功能,但是在不改变原来代码的情况下,于是有了下面的装饰器
     

    第一: 无参数的装饰器 

    基础平台  vim  basic.py 
    #装饰器函数
    def  auth(func):
        def inner():
            print "before"
            func() 
        return inner 
     
    #代码
    def  f1():
        print "f1  am ok"
    f1 = auth(f1)
    f1()
    业务平台调用 vim index.py 
    import basic 
    basic.f1()   
    执行过程:
    1 加载auth函数
    2 加载f1函数
    3 执行f1函数
    4 装饰器auth会将f1作为参数传入装饰器auth函数中
    5 执行auth函数 此时f1 = func 然后加载inner函数
    6 auth函数里面内容 返回inner函数
    7 执行inner函数
    8 打印print ,由于func=f1 此时执行的是f1()
    9 打印f1函数里面的内容
    简单理解为如下执行过程:
    f1 -> auth(f1) -> def inner():
                                       print "before" 
                                       f1() 
     
    使用python语法糖@符号来装饰函数
    def  auth(func):
        def inner():
            print "before"
            func() 
        return inner 
    @auth
    def  f1():
        print "f1  am ok"
    f1()
    整体过程详解如下图:
     
    第二: 带参数的装饰器 
     
    def login(user):
         if user = "bds":
                return True 
     
    def wrapper(func): 
            if login("user"): 
                return func 
    @wrapper
    def home():
            print "welcome user" 
    home() 
     
    上面的代码就不可以了 需要改成如下代码: 
     
    def  login(user):                           #定义了一个登陆函数
        if  user == 'bds':                      #判断用户
            return True     
    def warpper1(func):                         #定义了一个装饰器函数 home -->func
        def inner(argv):                        #内嵌函数 user -->argv
            if login(argv):                     #装饰成功先执行login函数 ,传递参数 user --> argv 
                print "func: " func             #
                return func(argv)               # 所以这里就是执行 home(argv),到这里才是真正执行home函数
            else:
                print  "auth false"
                return "error" 
        return inner    
    @warpper 1                                  #把home(user)当做参数加载到warpper1函数      
    def  home(user):
        print "welcome user"
        print "hello. ",user              
    home("bds")
    第三:对于参数数量不确定性的函数 
    #return返义回值需要赋值,定一个变量,然后打印变量,才会输出其返回的结果
     
     
    def wrapper2(func): #home --> func
    def inner(*args,**kwargs):             #a,b --> *args,**kwargs
    print "before "
    tmp = func(*args,**kwargs)             #当home函数有return时,进行赋值操作
    print "after "              
    return tmp                             #返回home函数中的return的返回值结果
    return inner
    @wrapper2
    def home(a,b):
    print "welcome user"
    return a+b
    
    num = home(2,1)                        #把return的返回结果进行变量赋值
    print num
                                         #打印结果就可以
    第四: 多个装饰器
     
    def wrapper3(func):
        def inner():
            print 'w3,before'
            func()
            print 'w3,after'
        return inner
     
    def wrapper4(func):
        def inner():
            print 'w4,before'
            func()
            print 'w4,after'
        return inner
     
    @wrapper4
    @wrapper3
    def foo():
        print 'foo'
     
    foo()
    运行结果:
    w2,before
    w1,before
    foo
    w1,after
    w2,after   
    结论:
        相当收到一个礼物 ,拆开一件礼物时,去掉外部一层又一层的包装 ,最后看到礼物,结果就是惊喜。。。

    第五:装饰器带参数

    def Before(request):
        print 'before'
     
    def After(request):
        print 'after'
     
    def Filter(before_func,after_func):
        def outer(main_func):
            def wrapper(request):
                before_result = before_func(request)
                if(before_result != None):
                    return before_result;
                main_result = main_func(request)
                if(main_result != None):
                    return main_result;
                after_result = after_func(request)
                if(after_result != None):
                    return after_result;
            return wrapper
        return outer
     
    @Filter(Before, After)
    def Index(request):
        print 'index'
     
    Index('example')
     
    先上结果:
    before
    index
    after
     
    简化过程:
    Index = Filter(Before,After)(Index(request))
     

    执行流程如下:

     

     
                                                                                  



    本文是纯属个人学习理解,如有遗漏误导,请大神果断指正......
  • 相关阅读:
    Android事件机制之一:事件传递和消费
    数据类型和JSON格式
    json 数据交换格式与java
    写给iOS程序员的命令行使用秘籍
    pthread_create线程创建的过程剖析
    同步变量及知识要素
    mysql 批量更新与批量更新多条记录的不同值实现方法
    gettype
    寻求全站搜索功能开发思路
    DEDE中 field:rel 是什么意思,起一个什么样的作用效果
  • 原文地址:https://www.cnblogs.com/budongshu/p/5021355.html
Copyright © 2011-2022 走看看