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

mac2026-05-28  2

装饰器

在代码运行期间动态增加功能的方式,称为装饰器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()
最新回复(0)