通过Python实现定时器和利用魔法方法改善友好交互

           实现Python的定时器是需要用到time库,其中需要调用的是localtime()方法,返回的是struct_time的时间格式,实际中只取前六位(年、月、日、时、分、秒)来达到实现计时的目的。今天的博文的重点有两个,一个是定时器实现计算间隔时间和两个间隔时间相加的过程,另一个是对魔法方法“__str__”和“__repr__”的理解和讨论。

           作为一个新手,写博文的过程是自己学习过程中的总结,方便与大家交流和自我回顾,这便是我写博文的初衷。今天的源码是一个视频教程上的案例,而我的原创就是基于源码的总结与收获。源码如下:

import time as t#这里相当一个重命名,为了以后调用方便,time就干脆命名为t

class MyTimer:
    def __init__(self):
        self.unit = ['年','月','天','小时','分钟','秒']
        self.prompt = '未开始计时'
        self.lasted = []
        self.begin = 0
        self.end = 0

    def __str__(self):
        return self.prompt

    __repr__ = __str__ #没有括号的应该,报错很明显如果后面有括号,那么肯定得具有形参

    def start(self):
        self.begin = t.localtime()
        self.prompt = "请先停止再进行新的开始"
        print("计时开始!")

    def stop(self):
        if not self.begin:
            #self.prompt = "请先开始调用start"
            print("请先调用start开始计时!")
        else:
            self.end = t.localtime()
            self._calc()
            print("计时结束!")

    def _calc(self):
        self.lasted = []
        self.prompt = "总共运行了"
        for index in range(6):
            self.lasted.append(self.end[index] - self.begin[index])
            if self.lasted[index]:
                self.prompt  += (str(self.lasted[index]) + self.unit[index])

        self.begin = 0
        self.end = 0

    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

          总的来说代码的逻辑还是挺清楚的,一共加了两处注释。一处是导入库时的更名操作,另一处是将魔法方法的__str__赋给__repr__,这里__str__不能写成__str__(),因为写成这样就需要一个位置参数,为空则报错,而如果再写成__str__(self),则会报self没有定义的错误。我的理解是,既然魔法方法是可以由自己来定义,而这一句的目的很明显,是将__str__方法返回的字符串的地址赋给__repr__。当检测到某实例对象的字符串形式的属性时会调用__str__,而这句代码又将__str__赋给__repr__,故返回的字符串实际地址中存的内容。如果有了括号,那么可能以为着__str__方法又重新定义。

          如果看到了这篇博文,又有兴趣尝试一下,我的建议是可以将源码放在Python的IDIE中新建的文件里,然后逐步进行尝试运行和分析,之后我会把我在IDIE上分析的过程详细讨论一下(尽管我粘上来的源码是在Pycharm上写的,哈哈,Pycharm舒服一点~~)

         我先简单说一下定时器的逻辑。除过构造方法和返回字符串的方法之外,还有四个方法,分别是记录开始时间(start())、记录终止时间(stop())、记录开始时间与终止时间之间的时间间隔(_calc(),这里定义为了一个内部方法)和重写的相加两个间隔时间的魔法方法(__add__(self,other))。根据之前对localtime()方法的解释,该方法返回的是一个列表,start()和stop()两个方法各自记录一个时刻,由_calc()方法根据两个时刻的差得到一个间隔时间,__add__方法的实现过程与_calc()类似。这两个方法的for循环,就是为了将得到的时刻由年至秒逐个相减(或相加),然后在给结果强制转换为字符串类型,方便连接之后的返回。

         下面是在IDIE中运行的内容:

=================== RESTART: D:/MajorDocuments/IDIEdoc.py ===================
>>> t1 = MyTimer()
>>> t1
未开始计时
>>> t1.start()
计时开始!
>>> t1.stop()
计时结束!
>>> t1
总共运行了11秒
>>> t2 = MyTimer()
>>> t2
未开始计时
>>> t2.stop()
请先开始start!
>>> t2.start()
计时开始!
>>> t2.start()
计时开始!
>>> t2
请先停止再进行新的开始
>>> t2.stop()
计时结束!
>>> t2
总共运行了32秒
>>> t1 + t2
'一共运行了43秒'
>>>
        

         t1和t2是类MyTimer的两个实例对象,首先在输入t1,构造方法中因为prompt的内容和__str__和__repr__,会打印prompt的内容。在start()方法中,会改写prompt,若输入t1,会将改写的prompt的打印出来,由此这里起到了一个提醒运行了start()而没有运行stop()的情况。同样在stop()中的if语句中,即在没有运行start()的情况下,会输出一句提醒没有开始。这里注释了一个改写prompt的代码,因为这句改写是不会输出的,除非是在先输入了stop()之后再输入t1,而这并不再是提醒的意思了。

        在__add__和_calc中也用到了prompt改写(严格地讲,应该都是新建一个字符串类型的对象,让prompt这个对象引用指向它)。

        连续两次输入start(),也就是在第二次再更新一下定义的开始时间的时刻,所以之后的stop()是以最后输入的start()的时刻为准。

       输入有过一对start()和stop()之后,再输入stop(),也就是连续两次输入stop()之后,第二次输入的结果会是返回一个请调用start()的提醒,原因是在_calc中的最后将实例对象的begin和end都重置为0。

       

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值