• 第44讲:魔方方法——简单定制


    一  基本要求

    • 定制一个计时器的类
    • start和stop方法代表启动计时和停止计时
    • 假设计时器对象t1,print(t1)和直接调用t1均显示结果
    • 当计时器未启动或已经停止计时时,调用stop方法会给予温馨提示
    • 两个计时器对象可以进行相加:t1+t2
    • 只能使用提供的有限资源完成

    二 需要的资源

    三 基本代码

    class43_MyTimer.py文件

     1 import time as t
     2 
     3 class MyTimer():
     4     def __init__(self):
     5         self.unit = ['','','','小时','分钟','']
     6         self.prompt = "未开始计时!"
     7         self.lasted = []
     8         self.begin = 0
     9         self.end = 0
    10     
    11     def __str__(self):
    12         return self.prompt
    13     
    14     __repr__ = __str__
    15     
    16     def __add__(self,other):
    17         prompt = "总共运行了"      # 临时使用,方法内部局部变量
    18         result = []
    19         for index in range(6):
    20             result.append(self.lasted[index] + other.lasted[index])
    21             if result[index]:
    22                 prompt += (str(result[index]) + self.unit[index])
    23         return prompt
    24     
    25     # 开始计时
    26     def start(self):
    27         self.begin = t.localtime()
    28         self.prompt = "提示:请先调用stop()停止计时!"
    29         print("计时开始...")
    30     
    31     # 停止计时
    32     def stop(self):
    33         if not self.begin:
    34             print("提示:请先调用start()进行计时!")
    35         else:
    36             self.end = t.localtime()
    37             self._calc()
    38             print("计时结束!")
    39     
    40     # 内部方法,计算运行时间
    41     def _calc(self):
    42         self.lasted = []
    43         self.prompt = "总共运行了"
    44         for index in range(6):
    45             self.lasted.append(self.end[index]-self.begin[index])
    46             if self.lasted[index]:
    47                 self.prompt += (str(self.lasted[index]) + self.unit[index])
    48         
    49         # 为下一轮计时初始化变量
    50         self.begin = 0
    51         self.end = 0

    运行结果:

     1 >>> import class43_MyTimer  as T
     2 >>> t1 = T.MyTimer()
     3 >>> t1.start()
     4 计时开始...
     5 >>> t1.stop()
     6 总共运行了6秒
     7 计时结束!
     8 >>> t2 = T.MyTimer()
     9 >>> t2
    10 未开始计时!
    11 >>> t2.stop()
    12 提示:请先调用start()进行计时!
    13 >>> t2.start()
    14 计时开始...
    15 >>> t2
    16 提示:请先调用stop()停止计时!
    17 >>> t2.stop()
    18 总共运行了1分钟-44秒
    19 计时结束!
    20 >>> t1 + t2
    21 '总共运行了1分钟-38秒'
    22 >>>

    四 课后习题

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

     1 import time as t
     2 
     3 class MyTimer():
     4     def __init__(self):
     5         self.unit = ['','','','小时','分钟','']
     6         self.borrow = [0,12,31,24,60,60]
     7         self.prompt = "未开始计时!"
     8         self.lasted = []
     9         self.begin = 0
    10         self.end = 0
    11     
    12     def __str__(self):
    13         return self.prompt
    14     
    15     __repr__ = __str__
    16     
    17     def __add__(self,other):
    18         prompt = "总共运行了"      # 临时使用,方法内部局部变量
    19         result = []
    20         for index in range(6):
    21             result.append(self.lasted[index] + other.lasted[index])
    22             if result[index]:
    23                 prompt += (str(result[index]) + self.unit[index])
    24         return prompt
    25     
    26     # 开始计时
    27     def start(self):
    28         self.begin = t.localtime()
    29         self.prompt = "提示:请先调用stop()停止计时!"
    30         print("计时开始...")
    31     
    32     # 停止计时
    33     def stop(self):
    34         if not self.begin:
    35             print("提示:请先调用start()进行计时!")
    36         else:
    37             self.end = t.localtime()
    38             self._calc()
    39             print("计时结束!")
    40     
    41     # 内部方法,计算运行时间
    42     def _calc(self):
    43         self.lasted = []
    44         self.prompt = "总共运行了"
    45         for index in range(6):
    46             temp = self.end[index]-self.begin[index]
    47             
    48             # 低位不够减,需要向高位借位
    49             if temp < 0:
    50                 # 测试高位是否有得借,没得借的话再向高位借......
    51                 i = 1
    52                 while self.lasted[index-i] < 1:
    53                     self.lasted[index-i] += self.borrow[index-i] - 1
    54                     self.lasted[index-i-1] -= 1
    55                     i += 1
    56                 
    57                 self.lasted.append(self.borrow[index] + temp)
    58                 self.lasted[index-1] -= 1
    59             else:
    60                 self.lasted.append(temp)
    61         
    62         # 由于高位随时会被借位,所以打印要放在最后
    63         for index in range(6):
    64             if self.lasted[index]:
    65                 self.prompt += str(self.lasted[index]) + self.unit[index]
    66         
    67         print(self.prompt)
    68         # 为下一轮计时初始化变量
    69         self.begin = 0
    70         self.end = 0
    ex44_0.py

    1.    相信大家已经意识到不对劲了:为毛一个月一定要31天?不知道有可能也是30天或者29天吗?(上一题我们的答案是假设一个月31天)

           没错,如果要正确得到月份的天数,我们还需要考虑是否闰年,还有每月的最大天数,所以太麻烦了……如果我们不及时纠正,我们会在错误的道路上越走越远……&

            所以,这一次,小甲鱼提出了更优秀的解决方案(Python官方推荐):用 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(object):
     4     def __init__(self):
     5         self.prompt = "未开始计时!"
     6         self.lasted = 0.0
     7         self.begin = 0
     8         self.end = 0
     9         self.default_timer = t.perf_counter
    10     
    11     def __str__(self):
    12         return self.prompt
    13     
    14     __repr__ = __str__
    15     
    16     def __add__(self,other):
    17         result = self.lasted + other.lasted
    18         prompt = "总共运行了%0.2f秒" % result
    19         return prompt
    20     
    21     # 开始计时
    22     def start(self):
    23         self.begin = self.default_timer()
    24         self.prompt = "提示:请先调用stop()停止计时!"
    25         print("计时开始...")
    26     
    27     # 停止计时
    28     def stop(self):
    29         if not self.begin:
    30             print("提示:请先调用start()进行计时!")
    31         else:
    32             self.end = self.default_timer()
    33             self._calc()
    34             print("计时结束!")
    35     
    36     # 内部方法,计算运行时间
    37     def _calc(self):
    38         self.lasted = self.end - self.begin
    39         self.prompt = "总共运行了%0.2f秒" % self.lasted
    40         print(self.prompt)
    41         
    42         # 为下一轮计时初始化变量
    43         self.begin = 0
    44         self.end = 0
    45     
    46     # 设置计时器(time.perf_counter()或time.process_time())
    47     # timer变量用来设置默认计时器,不调用set_timer函数的情况下,默认计时器是perf_counter
    48     def set_timer(self,timer):
    49         if timer == 'process_time':
    50             self.default_timer = t.process_time
    51         elif timer == 'perf_counter':
    52             self.default_timer = t.perf_counter
    53         else:
    54             print("输入无效,请输入perf_counter 或 process_time")
    ex44_1.py

    2. 既然咱都做到了这一步,那不如再深入一下。再次改进我们的代码,让它能够统计一个函数运行若干次的时间。
        要求一:函数调用的次数可以设置(默认是 1000000 次)
        要求二:新增一个 timing() 方法,用于启动计时器

    函数演示:

     1 >>> ================================ RESTART ================================
     2 >>> 
     3 >>> def test():
     4         text = "I love FishC.com!"
     5         char = 'o'
     6         if char in text:
     7                 pass
     8 
     9         
    10 >>> t1 = MyTimer(test)
    11 >>> t1.timing()
    12 >>> t1
    13 总共运行了 0.2714 >>> t2 = MyTimer(test, 100000000)
    15 >>> t2.timing()
    16 >>> t2
    17 总共运行了 25.9218 >>> t1 + t2
    19 '总共运行了 26.19 秒'

    代码:

    import time as t
    
    class MyTimer:
        def __init__(self, func, number=1000000):
            self.prompt = "未开始计时!"
            self.lasted = 0.0
            self.default_timer = t.perf_counter
            self.func = func
            self.number = number
        
        def __str__(self):
            return self.prompt
    
        __repr__ = __str__
    
        def __add__(self, other):
            result = self.lasted + other.lasted
            prompt = "总共运行了 %0.2f 秒" % result
            return prompt
    
        # 内部方法,计算运行时间
        def timing(self):
            self.begin = self.default_timer()
            for i in range(self.number):
                self.func()
            self.end = self.default_timer()
            self.lasted = self.end - self.begin
            self.prompt = "总共运行了 %0.2f 秒" % self.lasted
            
        # 设置计时器(time.perf_counter() 或 time.process_time())
        def set_timer(self, timer):
            if timer == 'process_time':
                self.default_timer = t.process_time
            elif timer == 'perf_counter':
                self.default_timer = t.perf_counter
            else:
                print("输入无效,请输入 perf_counter 或 process_time")
    ex44_2.py
  • 相关阅读:
    Codeforces 1093D(染色+组合数学)
    Codeforces 1093C (思维+贪心)
    Codeforces 1082D (贪心)
    Codeforces 433A (背包)
    BZOJ 3262(Treap+树状数组)
    BZOJ 1588 (treap)
    Codeforces 1061C (DP+滚动数组)
    Codeforces 1080C 题解(思维+二维前缀和)
    周记 2015.07.12
    周记 2015.07.04
  • 原文地址:https://www.cnblogs.com/luoxun/p/13587194.html
Copyright © 2020-2023  润新知