【Python044--魔法方法:简单定制】
一、简单定制
基本要求:
-- 定制一个计时器的类
-- 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--魔法方法:简单定制】的更多相关文章
- python:类4——魔法方法(定制序列、迭代)、生成器、推导式
一.定制序列(容器类型) http://bbs.fishc.com/forum.php?mod=viewthread&tid=48793&extra=page%3D1%26filter ...
- 洗礼灵魂,修炼python(40)--面向对象编程(10)—定制魔法方法+time模块
定制魔法方法 1.什么是定制魔法方法 首先定制是什么意思呢?其实就是自定义了,根据我们想要的要求来自定义.而在python中,其实那些所谓的内置函数,内置方法,内置属性之类的其实也是自定义出来的,不过 ...
- python_魔法方法(二):算术运算
python2.2之后,对类和类型做了同意,将int().float().str().list().touple()这些BIF转换为工厂函数 >>> type(len) <cl ...
- python_魔法方法(五):描述符和定制序列
描述符(property的原理) 描述符(descripto),用一句话来解释,描述符就是某种特殊的类的实例指派给另一个类的属性.那么什么是特殊类型的类呢?就是至少要在这个类中定义__get__(). ...
- 【Python】 魔法方法
魔法方法 这个名字真的很中二有没有 = =(或者说翻译气息太浓了,作为一个学外语的看到这种真是想吐槽的不行..) 从形式上来说,在方法的名字前后个加上两条下划线的就是魔法方法了 .从功能上说,所有魔法 ...
- 零基础学习python_魔法方法(41-48课)(迭代器)
接下来这个为啥要叫魔法方法呢,额,这个嘛我是跟小甲鱼的视频取的名字一样的,因为会讲比较多杂的东西,有... 魔法方法详细阅读地址:http://bbs.fishc.com/thread-48793-1 ...
- with上下文管理 python魔法方法
with语法在Python里很常见, 主要的利好是使用代码更简洁. 常见的使用场景有: 1. 资源对象的获取与释放. 使用with可以简化try...finally ... 2. 在不修改函数代码的前 ...
- 面向对象相关概念与在python中的面向对象知识(魔法方法+反射+元类+鸭子类型)
面向对象知识 封装 封装的原理是,其成员变量代表对象的属性,方法代表这个对象的动作真正的封装是,经过深入的思考,做出良好的抽象(设计属性时用到),给出“完整且最小”的接口,并使得内部细节可以对外透明( ...
- Python学习笔记(七)——魔法方法
1.构造和析造 魔法方法就是被双下划线包围的方法 __init__()方法 __init__方法默认没有参数,返回值为none.类实例化对象需有明确的初始化步骤要重写函数 >>> c ...
随机推荐
- ActiveMQ漏洞利用方法总结
转载来自:http://www.freebuf.com/column/161188.html 1.Console存在默认端口和默认密码/未授权访问(默认密码为admin:admin) ActiveMQ ...
- python 将文件大小转换为human readable 的大小表示
定义了一个函数, def HRS(size): units=('B','KB','MB','GB','TB','PB') for i in range(len(units)-1,-1,-1 ...
- python将目录切换为脚本所在目录
os.chdir(os.path.abspath(os.path.dirname(sys.argv[0])))
- Python之装饰器的实例
1.1装饰器的应用:参数类型检查 函数参数的检查,一定是在函数外 函数应该作为参数,传入到检查函数中 检查函数拿到函数传入的实际参数,与形参声明对比 __annotations__属性是一个字典,其中 ...
- c++ 常用的数据结构
set // constructing sets #include <iostream> #include <set> void checkin(std::set<int ...
- keras 上添加 roc auc指标
https://stackoverflow.com/questions/41032551/how-to-compute-receiving-operating-characteristic-roc-a ...
- D Tree Requests dfs+二分 D Pig and Palindromes -dp
D time limit per test 2 seconds memory limit per test 256 megabytes input standard input output stan ...
- python 试题归纳及答疑 更新中.....
一.Python基础篇(80题) 1.你为什么学习Python? 一.答题思路 1.阐述 python 优缺点 2.Python应用领域说明 3.根据自身工作情况阐述为什么会使用python 1)py ...
- 即时通讯(I)
网络通讯三要素: 网络七层协议划分: 网络五层协议的划分: 要记网络层的5层协议,可以把它想像为一枚洋葱.学过计算机网络的,看到这个网络协议的套接字,大概就会明白了!它是一层一层的进行包裹的,然后交由 ...
- arm cortex-m0plus源码学习(三)GPIO
概述: Cortex-m0的integration_kit提供三个GPIO接口,其中GPIO0传输到外部供用户使用,为EXTGPIO:GPIO1是内核自己的信号,不能乱改,会崩掉:GPIO2是一些中断 ...