学习装饰器,并设计一个装饰器,作用于函数上,打印函数执行时间-python

装饰器

在代码运行期间动态增加功能的方式,称为装饰器Decorator。常见的内置装饰器有:

  • @property
  • @setter

定一个装饰器升级now

装饰器 以一个函数作为参数,并返回一个函数


def log(f):
    def write_log(*args, **kw):  # 使用*是说可变参数,不限制参数的数量
        with open('./module2/a.txt', 'w') as f1:  
        # 这样写的好处是不用再单独写f1.close,他会自动关闭,不会造成资源的浪费
            f1.write(f.__name__)
            print('写入日志成功,函数名字是:%s' % f.__name__)
            return f(*args, **kw)
            # 返回的是f这个方法,是把now传进来,然后封装成write_log,然后再把now返回出来,同时也对now进行了执行
    return write_log
    # 传出来的也是一个方法
    # write_log 有两个功能,一个是打印日志的功能,一个是now打印日志的功能
    # 由于返回的是函数名write_log,而不是write_log(),所以write_log中的now并没有执行两遍,

调用方法1

ff = log(now)
# 传进了now方法
ff()
# 其实代表的是write_log方法
print(ff.__name__) 

调用方法2

这个方式比较反人类,所以用下面的@来进行装饰

import datetime
@log
def now():
    print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
now()

python 内置装饰器

学习 @property 和 @setter
原始代码:

class Student():
    def __init__(self, score):
        self.__score = score
    def get_score(self):
        return self.__score
    def set_score(self, value):
        if not isinstance(value, int):
            raise ValueError('Score must be an integer!')
        if value < 0 or value> 100:
            raise ValueError('Score must between 0~100!')
        self.__score = value
        
stu1 = Student(90)
print(stu1.get_score())
stu1.set_score(85)
print(stu1.get_score())

加上装饰器,方法变成属性

class Student():
    def __init__(self, score):
        self.__score = score

    @property    
    def score(self):
        return self.__score

    @score.setter
    def score(self, value):  
    	# 此时看着两个函数一样,但上面那个无参,下面这个有参
    	# 但尽量还是避免重复命名的参数
        if not isinstance(value, int):
            raise ValueError('Score must be an integer!')
        if value < 0 or value> 100:
            raise ValueError('Score must between 0~100!')
        self.__score = value

stu2 = Student('98')
print(stu2.score)
print(type(stu2.score))
stu2 = Student(67)
print(stu2.score)
print(type(stu2.score))
# stu2.score = '59'

运行之后,得到的结果是:

98
<class 'str'>
67
<class 'int'>

这里要注意一下程序的流程:

stu2 = Student('98')   
# 实例化一个对象stu2,同时调用__init__方法,将stu2的score属性变成了‘98’
print(stu2.score)   
# 这里对stu2.score进行打印,Python内置的@property装饰器就是负责把一个方法变成属性调用的,所以会将绑定了self的score属性进行打印
print(type(stu2.score)) 
# 根据上面的结果,此时输出的值就是字符串类型
stu2 = Student(67)  
# 和上面的字符串类型的一样,只不过这里传的参数是int类型的67
print(stu2.score)   
print(type(stu2.score)) 

若果代码换成:

stu2.score = 88
print(stu2.score)   
print(type(stu2.score)) 
stu2.score = '59'

会先输出:

88
<class 'int'>

然后报错,并且报错信息为我们自己定义的‘Score must be an integer!’’
在这里插入图片描述
这是因为这几句代码是先调用了被@score.setter装饰过的score方法,这样可以对stu2的score属性进行修改,而当传入的值为字符串类型的时候,就会提示我们自定义过的错误。

设计一个装饰器,作用于函数上,打印函数执行时间

import time

def metric(fn):	# 设计装饰器
    # 对程序进行封装
    def wrapper():
        # 在程序执行之前记录一次时间
        start_time = time.time()
        # 需要执行一次程序  
        fn()
        # 在程序执行之后记录一次时间
        end_time = time.time()
        # 两次时间相见,得到的差就是程序执行时间
        print('耗时:{:.8f}s'.format(end_time - start_time))    
    return wrapper

@metric
def multiplication_table():
	# 利用生成九九乘法表进行测试
    print('正常右上角写法的while思路')
    row = 9
    while row >= 1:
        col = row
        n = 0
        while n < 9 - row:
            print(' ' * 9, end='')
            n += 1
        while col >=1:
            print('{}*{}={:<5d}'.format(row, col, row * col),end='')
            col -= 1
        print('')
        row -= 1

multiplication_table()
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值