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))
 

执行流程如下:

 

 
                                                                              



本文是纯属个人学习理解,如有遗漏误导,请大神果断指正......
原文地址:https://www.cnblogs.com/budongshu/p/5021355.html