您的位置:首页 > 编程语言 > Python开发

[置顶] Python3装饰器的用法和心得,及装饰器作业

2018-02-22 21:18 656 查看

本文基于廖雪峰老师课程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
所以会判断出错,把这一行代码去掉就可以了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: