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所以会判断出错,把这一行代码去掉就可以了。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值