一、简单定制
基本要求:
-- 定制一个计时器的类
-- start和stop代表开始计时和停止计时
-- 假设计时器对象t1,print(t1)和直接调用t1均显示结果
-- 当计时器未启动或停止计时时,调用stop方法会给予温馨的提示
-- 两个计时器对象可以相加:t1 + t2
-- 只能使用提供的有限资源完成
=====================================================
程序编写之前需要了解一下资源(知识点)
-- 使用time模块的localtime方法获取时间
-- time.localtime()返回struct_time的时间格式
-- 表现你的类:__str__ 和 __repr__
解释:
返回struct_time时间格式
__str__ 和 __repr__
输入t1显示结果(显示字符串),要实现这个功能这时候就需要重写__str__ 和 __repr__方法
>>> class A: def __str__(self): return "I LOVE AI" >>> a = A() >>> print(a) I LOVE AI >>> class B: def __repr__(self): return " I LOVE AI" >>> b = B() >>> print(b) I LOVE AI >>> #要想实现print(对象)或者直接调用对象,就必须使用__str__ 和__repr__方法
整体程序的代码
import time as t class Mytimer(): def __init__(self): #定义一个列表存放时间的单位,以便程序运行后输出的结果直接是带单位的结果:如:总共运行了:3秒 self.unit = ['年','月','天','小时','分钟','秒'] self.prompt = '未开始计时!' self.lasted = [] #self.start = 0 self.begin = 0 #self.stop = 0 self.end = 0 #这里特别需要注意,方法名和属性名不能定义成同一个名字,否则属性会覆盖方法 #实现直接调用对象来输出内容 def __str__(self): return self.prompt #__str__ 赋值给 __repr__ __repr__ = __str__ #两个对象相加 def __add__(self,other): prompt = "总共运行了" result = [] for index in range(6): result.append(self.lasted[index]+other.lasted[index]) if result[index]:#如果result是空的话执行 prompt += (str(result[index])+self.unit[index]) return prompt #开始计时 def start(self):#self表示对象的引用 self.begin = t.localtime() self.prompt = '提示:请先调用stop()停止计时' print('计时开始...') #停止计时 def stop(self): if not self.begin: print("提示:请先调用start()进行计时!") else: self.end = t.localtime() #结束计时时并进行计算,即对象.内部方法 self._clac() print('计时结束!') #内部方法(_方法名),计算运行时间 def _clac(self): #计算的结果放在一个列表里面 self.lasted = [] #定义一个提示的变量 self.prompt = '总共运行了' #依次遍历localtime的索引 for index in range(6): #用结束时间减去开始时间得到运行的时间,并把结果放到lasted[]列表内 self.lasted.append(self.end[index]-self.begin[index]) #把每一次计算的结果进行一次追加 if self.lasted[index]: #当lasted为0时就不会执行if内的语句,而是执行下一轮的循环 self.prompt += str(self.lasted[index])+self.unit[index] #运行时间+单位 #为下一轮计时初始化变量 self.begin = 0 self.end = 0 执行结果: >>> t1 = Mytimer() >>> t1.start() 计时开始... >>> t1.stop() 计时结束! >>> t1 总共运行了9秒 >>> t2 = Mytimer() >>> t2.start() 计时开始... >>> t2.stop() 计时结束! >>> t2 总共运行了5秒 >>> t1+t2 '总共运行了14秒' >>>
二、按照课中的程序,如果开始计时的时间是(2022年2月22日16:30:30)停止时间是(2025年1月23日15:30:30),那按照我们用停止时间减开始时间的计算方式就会出现负数,你应该对此做一些转换
import time as t class MyTimer: def __init__(self): self.unit = ['年', '月', '天', '小时', '分钟', '秒'] self.borrow = [0, 12, 31, 24, 60, 60] self.prompt = "未开始计时!" self.lasted = [] self.begin = 0 self.end = 0 def __str__(self): return self.prompt __repr__ = __str__ def __add__(self, other): prompt = "总共运行了" result = [] for index in range(6): result.append(self.lasted[index] + other.lasted[index]) if result[index]: prompt += (str(result[index]) + self.unit[index]) return prompt # 开始计时 def start(self): self.begin = t.localtime() self.prompt = "提示:请先调用 stop() 停止计时!" print("计时开始...") # 停止计时 def stop(self): if not self.begin: print("提示:请先调用 start() 进行计时!") else: self.end = t.localtime() self._calc() print("计时结束!") ''' |-- print ("end+++", self.end[index],"\nbegin---", self.begin[index]) 打印出来理解end[index],begin[index] |-- for i in self.end: print ("====",i) 打印看self.end是如何的运行的 ''' # 内部方法,计算运行时间 def _calc(self): self.lasted = [] self.prompt = "总共运行了" for index in range(6): temp = self.end[index] - self.begin[index] print ("end+++", self.end[index],"\nbegin---", self.begin[index]) print("temp:",temp) # for i in self.end: # print ("====",i) print("\n") # 低位不够减,需向高位借位 if temp < 0: # 测试高位是否有得“借”,没得借的话向再高位借...... i = 1 while self.lasted[index - i] < 1: self.lasted[index - i] += self.borrow[index - i] - 1 self.lasted[index - i - 1] -= 1 i += 1 self.lasted.append(self.borrow[index] + temp) self.lasted[index - 1] -= 1 else: self.lasted.append(temp) # 由于高位随时会被借位,所以打印要放在最后 for index in range(6): if self.lasted[index]: self.prompt += str(self.lasted[index]) + self.unit[index] # 为下一轮计时初始化变量 self.begin = 0 self.end = 0 t1 = MyTimer() t1.start() print("begin==",t1.begin) t.sleep(5) t1.stop() #print("end==",t1.end) print(t1) 执行结果: 计时开始... begin== time.struct_time(tm_year=2018, tm_mon=11, tm_mday=2, tm_hour=16, tm_min=16, tm_sec=59, tm_wday=4, tm_yday=306, tm_isdst=0) end+++ 2018 begin--- 2018 temp: 0 end+++ 11 begin--- 11 temp: 0 end+++ 2 begin--- 2 temp: 0 end+++ 16 begin--- 16 temp: 0 end+++ 17 begin--- 16 temp: 1 end+++ 4 begin--- 59 temp: -55 计时结束! 总共运行了5秒
三、相信大家已经意识到不对劲了:为毛一个月一定要31天?不知道又可能也是30天或者29天吗?(上一题我们的答案是假设一个月31天)
没错,如果要正确得到月份的天数,我们还需要考虑是否闰年,还有每月的最大天数,所以太麻烦了......如果我们不及时纠正,我们会在错误的道理上越走越远.......
所以,这一次,小甲鱼提出来了更加优秀的解决方案:用time模块的perf_counter()和process_time()来计算,其中perf_counter()返回计时器的精准时间(系统的运行时间);process_time()返回当前进程执行CPU的时间总和
题目:改进我们课堂中的例子,这次试用perf_counter()和process_time()作为计时器。另外增加一个set_timer()方法,用于设置默认计时器(默认是perf_counter(),可以通过此方法修改为process_time())
import time as t class Mytimer(): def __init__(self): self.prompt = '未开始计时...' self.begin = 0 self.end = 0 self.lasted = 0.0 self.default_timer = t.perf_counter def __str__(self): return self.prompt __repr__ = __str__ def __add__(self, other): result = self.lasted + other.lasted prompt = '共运行了%0.2f秒'%result return prompt #开始计时 def start(self): self.begin = self.default_timer() self.prompt = '提示:请先调用stop结束计时。' print('开始计时...') #结束计时 def stop(self): if not self.begin: print("提示:请先调用start开始计时!") else: self.end = self.default_timer() self._clac() print("计时结束!") def _clac(self): self.lasted = self.end - self.begin self.prompt = "总共运行了%0.2f秒"%self.lasted print("end++",self.end,"\nbegin--",self.begin) print("process_time=",t.process_time(),"perf_counter=",t.perf_counter()) self.begin = 0 self.end = 0 #设置计时器(time.per_counter()) 和(time.process_time()) def set_timer(self,timer): if timer == 'process_time': self.default_timer = t.process_time() elif timer == 'per_counter': self.default_timer = t.perf_counter() else: print("输入无效:请输入per_counter()或者process_time()") t1 = Mytimer() t1.start() t.sleep(5) t1.stop() print(t1) 执行结果: 开始计时... end++ 79777.388179093 begin-- 79772.38780172 process_time= 0.040435 perf_counter= 79777.388454339 计时结束! 总共运行了5.00秒
四、既然咱都做到这一步,那不如深入一下,再次改进我们的代码,让它能够统计一个函数运行若干次的时间
要求一:函数调用的次数可以设置(默认是1000000次)
要求二:新增一个 timeing()方法,用于启动计时器
import time as t class Mytimer(): def __init__(self,func,number = 1000000): self.propmt = '未开始计时...' self.default_timer = t.perf_counter self.number = number #函数调用的次数,默认是1000000 self.lasted = 0.0 self.func = func def __str__(self): return self.propmt __repr__ = __str__ def __add__(self, other): result = self.lasted+other.lasted propmt = '共运行了%0.2f秒'%result return propmt #内部方法,计算运行时间 def timer(self): self.begin = self.default_timer() for i in range(self.number): self.func() print("number=",self.number,"\nfunc=",self.func()) self.end = self.default_timer() self.lasted = self.end - self.begin self.propmt = '共运行了%0.2f秒'%self.lasted #设置计时器(perf_counter和process_time) def set_timer(self,timer): if timer == 'perf_counter': self.default_timer = t.perf_counter() elif timer == 'process_time': self.default_timer = t.process_time() else: print("输入无效,请输入process_time或perf_counter") def test(): text = 'I love AI' char = 'o' for char in text: pass t1 = Mytimer(test) t1.timer() print(t1) t2 = Mytimer(test,1000000) t2.timer() print(t2) print(t1+t2) 执行结果: number= 1000000 func= None 共运行了0.30秒 number= 1000000 func= None 共运行了0.27秒 共运行了0.57秒