Python3装饰器的用法和心得,及装饰器作业
本文基于廖雪峰老师课程Python3写成,在学习过程当中会经常的发散性思维,力求把所有能考虑到的情况都考虑完全。(本文编辑器为Sublime Text3)
1、装饰器的用法和心得 a.下面为原代码:
def log(func): def wrapper(*args,**kw): print(call%s():%func.__name__) return func(*args,**kw) return wrapper @log def now(): print(2018-2-22) now()
得出结果:
callnow(): 2018-2-22 [Finished in 0.2s]
b.下面逐步讨论上面这个代码:
def log(func): def wrapper(*args,**kw): print(call%s():%func.__name__) return func(*args,**kw) return wrapper @log def now(): print(2018-2-22)
这看上去像一段返回函数,不过需要注意的有两点。
第一点: 括号里面的func参数到时候赋值进去的是一段新函数,@log下面的函数块
def now(): print(2018-2-22)
会产生一个一模一祥的函数块到func参数里面去,而不是它自己本身赋值进去。(@+需要调用的函数,@log函数代表调用log函数,(函数如果没有人调用它们则不会运行)下面必须还需要自己写一段函数作为赋值的参数)。
第二点:wrapper(*args,**kw) wrapper()括号里面的*args,**kw前面的星号都是必要的,如果没有将会产生错误
TypeError: wrapper() missing 1 required positional argument: args
而这两个星号的参数需要放在哪儿呢,及当@log下面的函数
def now(): print(2018-2-22)
= (一个函数)
def wrapper(*args,**kw):#这里面的*args,*kw其实已经被新函数def now(): print(2018-2-22)赋值或者说替代掉了。 print(call%s():%func.__name__) return func(*args,**kw)
的时候,就需要在后边的函数参数里面写入*args,**kw(代表可以传入任何参数,廖雪峰老师说:now = log(now)。就是我把老师的公式给展开来)。还有一点需要注意:最后调用
now()
函数得到的不是print(‘2018-2-22’),而是
def wrapper(*args,**kw): print(call%s():%func.__name__) return func(*args,**kw)
这个代码块的结果,也许这就是@的用法吧。。。
第三点:我们来讨论一下,一个星号和两个星号的区别(不局限于上面代码): 1、一个星号*的用法: 代表可以传入任何非关键字,显示出来的就会变成一个元组,看下面代码:
def prints(*arg): print (arg); print(prints (1,2,3,4,5,6,7))
打印的结果是一个元组: (1,2,3,4,5,6,7) , 也就是说该参数(arg) 将传进来的所有参数放在了一个元组中。 2、两个星号的用法 传入关键字,显示出来的就是一个dic,有key和value值。(所以在有两个星号的参数中我们需要传入两个参数作为一组,比如:a=1,b=2,c=3,d=4,e=5,f=6,g=7),代码如下:
def dics(**arg): print (arg) print(dics(a=1,b=2,c=3,d=4,e=5,f=6,g=7))
结果为:
{ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7}
课后作业:
import time,functools def metric(fn): @functools.wraps(fn) def log(*args,**kw): print(fn():%s%time.ctime())(这里可以不用加) print(fn(*args,**kw)) return log @metric def fast(x,y): time.sleep(0.0012) return x+y; @metric def slow(x,y,z): time.sleep(0.1234) return x*y*z; f=fast(11,22) s=slow(11,22,33) if f !=33: print(测试失败) elif s!=7986: print(测试失败)
结果为:
fn():Fri Feb 23 21:02:55 2018 33 fn():Fri Feb 23 21:02:55 2018 7986 测试失败
为什么不出现测试失败呢,因为我在代码中加入了这一行代码print(fn():%s%time.ctime()),结果会出现fn():Fri Feb 23 21:02:55 2018所以会判断出错,把这一行代码去掉就可以了。