一、简单定制

基本要求:

-- 定制一个计时器的类

-- start和stop代表开始计时和停止计时

-- 假设计时器对象t1,print(t1)和直接调用t1均显示结果

-- 当计时器未启动或停止计时时,调用stop方法会给予温馨的提示

-- 两个计时器对象可以相加:t1 + t2

-- 只能使用提供的有限资源完成

=====================================================

程序编写之前需要了解一下资源(知识点)

-- 使用time模块的localtime方法获取时间

-- time.localtime()返回struct_time的时间格式

-- 表现你的类:__str__ 和 __repr__

解释:

返回struct_time时间格式

__str__  和 __repr__

输入t1显示结果(显示字符串),要实现这个功能这时候就需要重写__str__ 和 __repr__方法

  1. >>> class A:
  2. def __str__(self):
  3. return "I LOVE AI"
  4.  
  5. >>> a = A()
  6. >>> print(a)
  7. I LOVE AI
  8. >>> class B:
  9. def __repr__(self):
  10. return " I LOVE AI"
  11.  
  12. >>> b = B()
  13. >>> print(b)
  14. I LOVE AI
  15. >>>
  16.  
  17. #要想实现print(对象)或者直接调用对象,就必须使用__str__ 和__repr__方法

整体程序的代码

  1. import time as t
  2.  
  3. class Mytimer():
  4. def __init__(self):
  5. #定义一个列表存放时间的单位,以便程序运行后输出的结果直接是带单位的结果:如:总共运行了:3秒
  6. self.unit = ['年','月','天','小时','分钟','秒']
  7. self.prompt = '未开始计时!'
  8. self.lasted = []
  9. #self.start = 0
  10. self.begin = 0
  11. #self.stop = 0
  12. self.end = 0
  13. #这里特别需要注意,方法名和属性名不能定义成同一个名字,否则属性会覆盖方法
  14.  
  15. #实现直接调用对象来输出内容
  16. def __str__(self):
  17. return self.prompt
  18.  
  19. #__str__ 赋值给 __repr__
  20. __repr__ = __str__
  21.  
  22. #两个对象相加
  23. def __add__(self,other):
  24. prompt = "总共运行了"
  25. result = []
  26. for index in range(6):
  27. result.append(self.lasted[index]+other.lasted[index])
  28. if result[index]:#如果result是空的话执行
  29. prompt += (str(result[index])+self.unit[index])
  30. return prompt
  31.  
  32. #开始计时
  33. def start(self):#self表示对象的引用
  34. self.begin = t.localtime()
  35. self.prompt = '提示:请先调用stop()停止计时'
  36. print('计时开始...')
  37.  
  38. #停止计时
  39. def stop(self):
  40. if not self.begin:
  41. print("提示:请先调用start()进行计时!")
  42. else:
  43. self.end = t.localtime()
  44. #结束计时时并进行计算,即对象.内部方法
  45. self._clac()
  46. print('计时结束!')
  47.  
  48. #内部方法(_方法名),计算运行时间
  49. def _clac(self):
  50. #计算的结果放在一个列表里面
  51. self.lasted = []
  52. #定义一个提示的变量
  53. self.prompt = '总共运行了'
  54. #依次遍历localtime的索引
  55. for index in range(6):
  56. #用结束时间减去开始时间得到运行的时间,并把结果放到lasted[]列表内
  57. self.lasted.append(self.end[index]-self.begin[index])
  58. #把每一次计算的结果进行一次追加
  59. if self.lasted[index]: #当lasted为0时就不会执行if内的语句,而是执行下一轮的循环
  60. self.prompt += str(self.lasted[index])+self.unit[index] #运行时间+单位
  61.  
  62. #为下一轮计时初始化变量
  63. self.begin = 0
  64. self.end = 0
  65.  
  66. 执行结果:
  67. >>> t1 = Mytimer()
  68. >>> t1.start()
  69. 计时开始...
  70. >>> t1.stop()
  71. 计时结束!
  72. >>> t1
  73. 总共运行了9
  74. >>> t2 = Mytimer()
  75. >>> t2.start()
  76. 计时开始...
  77. >>> t2.stop()
  78. 计时结束!
  79. >>> t2
  80. 总共运行了5
  81. >>> t1+t2
  82. '总共运行了14秒'
  83. >>>

二、按照课中的程序,如果开始计时的时间是(2022年2月22日16:30:30)停止时间是(2025年1月23日15:30:30),那按照我们用停止时间减开始时间的计算方式就会出现负数,你应该对此做一些转换

  1. import time as t
  2.  
  3. class MyTimer:
  4.  
  5. def __init__(self):
  6. self.unit = ['年', '月', '天', '小时', '分钟', '秒']
  7. self.borrow = [0, 12, 31, 24, 60, 60]
  8. self.prompt = "未开始计时!"
  9. self.lasted = []
  10. self.begin = 0
  11. self.end = 0
  12.  
  13. def __str__(self):
  14. return self.prompt
  15.  
  16. __repr__ = __str__
  17.  
  18. def __add__(self, other):
  19. prompt = "总共运行了"
  20. result = []
  21. for index in range(6):
  22. result.append(self.lasted[index] + other.lasted[index])
  23. if result[index]:
  24. prompt += (str(result[index]) + self.unit[index])
  25. return prompt
  26.  
  27. # 开始计时
  28. def start(self):
  29. self.begin = t.localtime()
  30. self.prompt = "提示:请先调用 stop() 停止计时!"
  31. print("计时开始...")
  32.  
  33. # 停止计时
  34. def stop(self):
  35. if not self.begin:
  36. print("提示:请先调用 start() 进行计时!")
  37. else:
  38. self.end = t.localtime()
  39. self._calc()
  40. print("计时结束!")
  41.  
  42. '''
  43. |-- print ("end+++", self.end[index],"\nbegin---", self.begin[index]) 打印出来理解end[index],begin[index]
  44. |-- for i in self.end:
  45. print ("====",i) 打印看self.end是如何的运行的
  46. '''
  47.  
  48. # 内部方法,计算运行时间
  49. def _calc(self):
  50. self.lasted = []
  51. self.prompt = "总共运行了"
  52. for index in range(6):
  53. temp = self.end[index] - self.begin[index]
  54. print ("end+++", self.end[index],"\nbegin---", self.begin[index])
  55. print("temp:",temp)
  56. # for i in self.end:
  57. # print ("====",i)
  58. print("\n")
  59.  
  60. # 低位不够减,需向高位借位
  61. if temp < 0:
  62. # 测试高位是否有得“借”,没得借的话向再高位借......
  63. i = 1
  64. while self.lasted[index - i] < 1:
  65. self.lasted[index - i] += self.borrow[index - i] - 1
  66. self.lasted[index - i - 1] -= 1
  67. i += 1
  68.  
  69. self.lasted.append(self.borrow[index] + temp)
  70. self.lasted[index - 1] -= 1
  71. else:
  72. self.lasted.append(temp)
  73.  
  74. # 由于高位随时会被借位,所以打印要放在最后
  75. for index in range(6):
  76. if self.lasted[index]:
  77. self.prompt += str(self.lasted[index]) + self.unit[index]
  78.  
  79. # 为下一轮计时初始化变量
  80. self.begin = 0
  81. self.end = 0
  82.  
  83. t1 = MyTimer()
  84. t1.start()
  85. print("begin==",t1.begin)
  86. t.sleep(5)
  87. t1.stop()
  88. #print("end==",t1.end)
  89. print(t1)
  90.  
  91. 执行结果:
  92. 计时开始...
  93. 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)
  94. end+++ 2018
  95. begin--- 2018
  96. temp: 0
  97.  
  98. end+++ 11
  99. begin--- 11
  100. temp: 0
  101.  
  102. end+++ 2
  103. begin--- 2
  104. temp: 0
  105.  
  106. end+++ 16
  107. begin--- 16
  108. temp: 0
  109.  
  110. end+++ 17
  111. begin--- 16
  112. temp: 1
  113.  
  114. end+++ 4
  115. begin--- 59
  116. temp: -55
  117.  
  118. 计时结束!
  119. 总共运行了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())

  1. import time as t
  2.  
  3. class Mytimer():
  4.  
  5. def __init__(self):
  6. self.prompt = '未开始计时...'
  7. self.begin = 0
  8. self.end = 0
  9. self.lasted = 0.0
  10. self.default_timer = t.perf_counter
  11.  
  12. def __str__(self):
  13. return self.prompt
  14.  
  15. __repr__ = __str__
  16.  
  17. def __add__(self, other):
  18. result = self.lasted + other.lasted
  19. prompt = '共运行了%0.2f秒'%result
  20. return prompt
  21.  
  22. #开始计时
  23. def start(self):
  24. self.begin = self.default_timer()
  25. self.prompt = '提示:请先调用stop结束计时。'
  26. print('开始计时...')
  27.  
  28. #结束计时
  29. def stop(self):
  30. if not self.begin:
  31. print("提示:请先调用start开始计时!")
  32. else:
  33. self.end = self.default_timer()
  34. self._clac()
  35. print("计时结束!")
  36.  
  37. def _clac(self):
  38. self.lasted = self.end - self.begin
  39. self.prompt = "总共运行了%0.2f秒"%self.lasted
  40. print("end++",self.end,"\nbegin--",self.begin)
  41. print("process_time=",t.process_time(),"perf_counter=",t.perf_counter())
  42.  
  43. self.begin = 0
  44. self.end = 0
  45.  
  46. #设置计时器(time.per_counter()) 和(time.process_time())
  47. def set_timer(self,timer):
  48. if timer == 'process_time':
  49. self.default_timer = t.process_time()
  50. elif timer == 'per_counter':
  51. self.default_timer = t.perf_counter()
  52. else:
  53. print("输入无效:请输入per_counter()或者process_time()")
  54.  
  55. t1 = Mytimer()
  56. t1.start()
  57. t.sleep(5)
  58. t1.stop()
  59. print(t1)
  60.  
  61. 执行结果:
  62. 开始计时...
  63. end++ 79777.388179093
  64. begin-- 79772.38780172
  65. process_time= 0.040435 perf_counter= 79777.388454339
  66. 计时结束!
  67. 总共运行了5.00

四、既然咱都做到这一步,那不如深入一下,再次改进我们的代码,让它能够统计一个函数运行若干次的时间

要求一:函数调用的次数可以设置(默认是1000000次)

要求二:新增一个 timeing()方法,用于启动计时器

  1. import time as t
  2.  
  3. class Mytimer():
  4.  
  5. def __init__(self,func,number = 1000000):
  6. self.propmt = '未开始计时...'
  7. self.default_timer = t.perf_counter
  8. self.number = number #函数调用的次数,默认是1000000
  9. self.lasted = 0.0
  10. self.func = func
  11.  
  12. def __str__(self):
  13. return self.propmt
  14.  
  15. __repr__ = __str__
  16.  
  17. def __add__(self, other):
  18. result = self.lasted+other.lasted
  19. propmt = '共运行了%0.2f秒'%result
  20. return propmt
  21.  
  22. #内部方法,计算运行时间
  23. def timer(self):
  24. self.begin = self.default_timer()
  25. for i in range(self.number):
  26. self.func()
  27. print("number=",self.number,"\nfunc=",self.func())
  28. self.end = self.default_timer()
  29. self.lasted = self.end - self.begin
  30. self.propmt = '共运行了%0.2f秒'%self.lasted
  31.  
  32. #设置计时器(perf_counter和process_time)
  33. def set_timer(self,timer):
  34. if timer == 'perf_counter':
  35. self.default_timer = t.perf_counter()
  36. elif timer == 'process_time':
  37. self.default_timer = t.process_time()
  38. else:
  39. print("输入无效,请输入process_time或perf_counter")
  40.  
  41. def test():
  42. text = 'I love AI'
  43. char = 'o'
  44. for char in text:
  45. pass
  46.  
  47. t1 = Mytimer(test)
  48. t1.timer()
  49. print(t1)
  50.  
  51. t2 = Mytimer(test,1000000)
  52. t2.timer()
  53. print(t2)
  54.  
  55. print(t1+t2)
  56.  
  57. 执行结果:
  58. number= 1000000
  59. func= None
  60. 共运行了0.30
  61. number= 1000000
  62. func= None
  63. 共运行了0.27
  64. 共运行了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. ActiveMQ漏洞利用方法总结

    转载来自:http://www.freebuf.com/column/161188.html 1.Console存在默认端口和默认密码/未授权访问(默认密码为admin:admin) ActiveMQ ...

  2. python 将文件大小转换为human readable 的大小表示

    定义了一个函数, def HRS(size):    units=('B','KB','MB','GB','TB','PB')    for i in range(len(units)-1,-1,-1 ...

  3. python将目录切换为脚本所在目录

    os.chdir(os.path.abspath(os.path.dirname(sys.argv[0])))

  4. Python之装饰器的实例

    1.1装饰器的应用:参数类型检查 函数参数的检查,一定是在函数外 函数应该作为参数,传入到检查函数中 检查函数拿到函数传入的实际参数,与形参声明对比 __annotations__属性是一个字典,其中 ...

  5. c++ 常用的数据结构

    set // constructing sets #include <iostream> #include <set> void checkin(std::set<int ...

  6. keras 上添加 roc auc指标

    https://stackoverflow.com/questions/41032551/how-to-compute-receiving-operating-characteristic-roc-a ...

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

  8. python 试题归纳及答疑 更新中.....

    一.Python基础篇(80题) 1.你为什么学习Python? 一.答题思路 1.阐述 python 优缺点 2.Python应用领域说明 3.根据自身工作情况阐述为什么会使用python 1)py ...

  9. 即时通讯(I)

    网络通讯三要素: 网络七层协议划分: 网络五层协议的划分: 要记网络层的5层协议,可以把它想像为一枚洋葱.学过计算机网络的,看到这个网络协议的套接字,大概就会明白了!它是一层一层的进行包裹的,然后交由 ...

  10. arm cortex-m0plus源码学习(三)GPIO

    概述: Cortex-m0的integration_kit提供三个GPIO接口,其中GPIO0传输到外部供用户使用,为EXTGPIO:GPIO1是内核自己的信号,不能乱改,会崩掉:GPIO2是一些中断 ...