装饰器分步解释-形成过程:
#-*- coding: UTF-8 -*- #示例1: def deco(p_args): def pack(): print('haha,i am deco fun') print('i want to use parent fun arg: '+p_args) print('haha,i am deco fun--finished ') return pack deco('abc') #执行结果无返回值 deco('abc')() #执行结果同示例2 #示例2: def deco(p_args): def pack(): print('haha,i am deco fun') print('i want to use parent fun arg: '+p_args) print('haha,i am deco fun--finished ') return pack() #需要加上小括号,否则pack函数不会被执行 deco('abc') #执行结果返回如下: #haha,i am deco fun #there are 2 args.they are: #haha,i am deco fun--finished #示例3: def myf(): print('i want to be decorated.') def deco(fun): def pack(): print('haha,i am deco fun') #print('i want to use parent fun arg: '+p_args) fun() print('haha,i am deco fun--finished ') return pack #此处不加括号,deco(myf)执行结果无返回。同示例1 deco(myf) #执行结果无返回。 deco(myf)() #执行结果同示例4 #示例4: def myf(): print('i want to be decorated.') def deco(fun): def pack(): print('haha,i am deco fun') #print('i want to use parent fun arg: '+p_args) fun() print('haha,i am deco fun--finished ') return pack() #加括号,deco(myf)执行结果输出如下,同示例2 deco(myf) #将myf函数传给deco函数的参数fun。 #haha,i am deco fun #i want to be decorated. #haha,i am deco fun--finished #示例5: def myf(): print('i want to be decorated.') def deco(fun): def pack(): print('haha,i am deco fun') #print('i want to use parent fun arg: '+p_args) fun() print('haha,i am deco fun--finished ') return pack #此处不加括号,而是在最外面的函数执行的时候再加括号执行,如deco(myf)() #deco(myf)()的执行结果等价于如下,输出结果同示例4: myf1 = deco(myf) myf1() #haha,i am deco fun #i want to be decorated. #haha,i am deco fun--finished #此处的变量myf1跟myf没有任何关系,只是将deco(myf)这个函数赋予了变量myf1,然后再通过myf1()的方式执行该函数。所以可以将myf1重新写为myf,就成了装饰器的效果,如示例6。 myf = deco(myf) myf() #示例6--装饰器: def deco(fun): def pack(): print('haha,i am deco fun----') #print('i want to use parent fun arg: '+p_args) fun() print('haha,i am deco fun--finished ') return pack #此处不加括号,而是在最外面的函数执行的时候再加括号执行,如deco(myf)() @deco def myf(): print('i want to be decorated,6.') myf()
装饰器中的函数参数传递:
def deco(fun): def pack(*args,**kwargs): #这样写可以传递任意参数。也可以直接写name,age,只是这样在其他函数调用的时候会出错,因为其他函数的参数可能并不是name,age等。。。 print('haha,i am deco fun') print('there are %d args.they are: %s %d' %(len(args),args[0],args[1])) #调用原函数的参数 fun(*args,**kwargs) print('haha,i am deco fun--finished') return pack @deco #将sayhi传给deco的参数fun def sayhi(name,age): print('helo,i am %s ,my age is %d.'%(name,age)) sayhi('LiuXue',20) #返回结果: haha,i am deco fun there are 2 args.they are: LiuXue 20 helo,i am LiuXue ,my age is 20. haha,i am deco fun--finished
#定义函数: def hello(*args,**kw): print 'ab' print args print kw args=range(1,5) hello(args) #返回值: ab ([1, 2, 3, 4],) {} #定义装饰函数: def dec(fun): def wrapper(*args,**kw): print 'do sth. before' fun(*args,**kw) print 'do sth. after' return wrapper dec(hello(args)) #将hello函数及参数当做变量赋予dec,只相当于直接执行hello(args),返回值: ab ([1, 2, 3, 4],) {} p=dec(hello) p(args) dec(hello)(args) #将函数当做变量赋予dec,然后通过变量调用函数,再赋予变量变量,返回值: do sth. before ab ([1, 2, 3, 4],) {} do sth. after
def dec(fun): def wrapper(*args,**kw): print 'do sth. before' fun(*args,**kw) #此处如果改为 return fun(*args,**kw),则下一句print 'after'不会再执行。在函数中,遇到第一个return则不会再执行后面的语句,如果返回两个值,可以写在同一行。如果用了return,函数执行完会得到结果,没有return则无返回值 print 'do sth. after' return wrapper @dec #通过@调用装饰函数 def hello(*args,**kw): print 'ab' print args print kw args=range(1,5) hello(args)
装饰器自身接收参数:
# -*- coding: UTF-8 -*- def deco(darg): #装饰函数的参数 print darg def getFun(func): def pack(name,age): #这样写可以传递任意参数。也可以直接写name,age,只是这样在其他函数调用的时候会出错,因为其他函数的参数可能并不是name,age等。。。 print('haha,i am darg: '+darg) #装饰函数的参数可以传入使用 print('there are args.they are: %s %d' %(name,age)) #调用原函数的参数 func(name,age) print('haha,i am deco fun--finished') return pack return getFun @deco('abc') #装饰函数调用参数‘abc’ def sayhi(name,age): m=15 print('helo,i am %s ,my age is %d.'%(name,age)) name='LiuXue' age=20 sayhi(name,age) # #返回结果: abc haha,i am darg: abc there are args.they are: LiuXue 20 helo,i am LiuXue ,my age is 20. haha,i am deco fun--finished