一、简单定制

基本要求:

-- 定制一个计时器的类

-- 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秒

【Python044--魔法方法:简单定制】的更多相关文章

  1. python:类4——魔法方法(定制序列、迭代)、生成器、推导式

    一.定制序列(容器类型) http://bbs.fishc.com/forum.php?mod=viewthread&tid=48793&extra=page%3D1%26filter ...

  2. 洗礼灵魂,修炼python(40)--面向对象编程(10)—定制魔法方法+time模块

    定制魔法方法 1.什么是定制魔法方法 首先定制是什么意思呢?其实就是自定义了,根据我们想要的要求来自定义.而在python中,其实那些所谓的内置函数,内置方法,内置属性之类的其实也是自定义出来的,不过 ...

  3. python_魔法方法(二):算术运算

    python2.2之后,对类和类型做了同意,将int().float().str().list().touple()这些BIF转换为工厂函数 >>> type(len) <cl ...

  4. python_魔法方法(五):描述符和定制序列

    描述符(property的原理) 描述符(descripto),用一句话来解释,描述符就是某种特殊的类的实例指派给另一个类的属性.那么什么是特殊类型的类呢?就是至少要在这个类中定义__get__(). ...

  5. 【Python】 魔法方法

    魔法方法 这个名字真的很中二有没有 = =(或者说翻译气息太浓了,作为一个学外语的看到这种真是想吐槽的不行..) 从形式上来说,在方法的名字前后个加上两条下划线的就是魔法方法了 .从功能上说,所有魔法 ...

  6. 零基础学习python_魔法方法(41-48课)(迭代器)

    接下来这个为啥要叫魔法方法呢,额,这个嘛我是跟小甲鱼的视频取的名字一样的,因为会讲比较多杂的东西,有... 魔法方法详细阅读地址:http://bbs.fishc.com/thread-48793-1 ...

  7. with上下文管理 python魔法方法

    with语法在Python里很常见, 主要的利好是使用代码更简洁. 常见的使用场景有: 1. 资源对象的获取与释放. 使用with可以简化try...finally ... 2. 在不修改函数代码的前 ...

  8. 面向对象相关概念与在python中的面向对象知识(魔法方法+反射+元类+鸭子类型)

    面向对象知识 封装 封装的原理是,其成员变量代表对象的属性,方法代表这个对象的动作真正的封装是,经过深入的思考,做出良好的抽象(设计属性时用到),给出“完整且最小”的接口,并使得内部细节可以对外透明( ...

  9. Python学习笔记(七)——魔法方法

    1.构造和析造 魔法方法就是被双下划线包围的方法 __init__()方法 __init__方法默认没有参数,返回值为none.类实例化对象需有明确的初始化步骤要重写函数 >>> c ...

随机推荐

  1. Hibernate框架第三天

    **课程回顾:Hibernate第二天** 1. 持久化类和一级缓存 * 持久化类:JavaBean + 映射的配置文件 * 持久化对象的三种状态 * 瞬时态 * 持久态:有自动更新数据的能力 * 托 ...

  2. 编写一个程序解决选择问题。令k=N/2。

    import java.util.Arrays; /** * 选择问题,确定N个数中第K个最大值 * @author wulei * 将前k个数读进一个数组,冒泡排序(递减),再将剩下的元素逐个读入, ...

  3. Sublime text3 经常出现 “ There are no packages avaliable for installation” 解决方法

    对应这个问题,一开始在度娘上找到很多答案,包括将json文件放在本地然后通过 package setting 更改的,发现其实不好使,原因未知. 后来测试了在hosts文件添加sublime text ...

  4. Vue系列之 => 使用钩子函数的第二个参数传参

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 即时通信系统中实现全局系统通知,并与Web后台集成【附C#开源即时通讯系统(支持广域网)——QQ高仿版IM最新源码】

    像QQ这样的即时通信软件,时不时就会从桌面的右下角弹出一个小窗口,或是显示一个广告.或是一个新闻.或是一个公告等.在这里,我们将其统称为“全局系统通知”.很多使用C#开源即时通讯系统——GGTalk的 ...

  6. kali长时间未使用导致数字签名过期无法更新源解决办法

    kali长时间未使用,数字签名会过期,从而导致无法更新源. apt-get update:从源(Source)服务器那里下载最新的软件包列: apt-get upgrade:对已经安装的软件包本身进行 ...

  7. Django 创建项目流程

    django 项目创建流程 1 创建项目 cmd django-admin startproject 项目名称 pycharm file -- new project -- Django -- 项目名 ...

  8. 算法提高 P0102

    用户输入三个字符,每个字符取值范围是0-9,A-F.然后程序会把这三个字符转化为相应的十六进制整数,并分别以十六进制,十进制,八进制输出,十六进制表示成3位,八进制表示成4位,若不够前面补0.(不考虑 ...

  9. ubuntu 18.04下安装Hadoop

    在Ubuntu里装完Java环境后,接下来就开始学习安装Hadoop了,参照的是以下链接 https://blog.csdn.net/xuan314708889/article/details/805 ...

  10. SpringMVC实现 MultipartFile 文件上传

    1. Maven 工程引入所需要的依赖包 2. 页面需要开放多媒体标签 3. 配置文件上传试图解析器 4. 接收图片信息,通过 IO 流写入磁盘(调用解析其中的方法即可) 如下: 1.1 引入所依赖的 ...