zoukankan      html  css  js  c++  java
  • 【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],"
    begin---", 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],"
    begin---", self.begin[index])
                print("temp:",temp)
                # for i in self.end:
                #     print ("====",i)
                print("
    ")
    
                # 低位不够减,需向高位借位
                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,"
    begin--",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,"
    func=",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秒
  • 相关阅读:
    js 判断多个一样的name
    VisualSVN Server的配置和使用方法 图文
    file get contents 访问不了域名原因
    js confirm函数 删除提示
    关于PHP的curl开启问题
    重置svn地址
    google 火狐 模拟显示手机页面插件
    开启Apache mod_rewrite模块完全解答
    zend studio 9.0.4 破解、汉化和字体颜色及快捷键相关设置
    zend studio 8 修字体和大小
  • 原文地址:https://www.cnblogs.com/frankruby/p/9873801.html
Copyright © 2011-2022 走看看