• python_魔法方法(三):__str__()和__repr__()


    使用python的魔法方法和time模块定制一个计时器的类

    1.用time模块里的localtime()方法获取时间
    2.time.localtime返回struct_time格式
    3.表现你的类:__str__()和__repr__()
    先来看下__str__()和__repr__()魔法方法
    >>> class A():
        def __str__(self):
            return "我在学习python"
        
    >>> a = A()
    >>> print(a)
    我在学习python
    >>> a
    <__main__.A object at 0x0000000002F6AB70>
    >>> class B():
        def __repr__(self):
            return "python要一起学习的"
        
    >>> b = B()
    >>> b
    python要一起学习的
    >>> print(b)
    python要一起学习的

    看到这里知道要怎么写了吗,如果还是比较蒙的,那就继续往下看吧

    首先用到一个time模块,我们先导入time模块

    其次是两个功能,一个是开始时间,一个是结束时间:

    >>> import time as t
    >>> class MyTimer():
        def start(self):
            self.start = t.localtime()
            print("计时开始。。。")
        def stop(self):
            self.stop = t.localtime()
            self.__calc()
            print("结束计时。。。")
        def __calc(self):
            self.lasted = []
            self.prompt ="总共运行了"
            for index in range(6):
                self.lasted.append(self.stop[index] - self.start[index])
                self.prompt += str(self.lasted[index])
            print(self.prompt)
    
            
    >>> t1 = MyTimer()
    >>> t1.start()
    计时开始。。。
    >>> t1.stop()
    总共运行了000008
    结束计时。。。

    基本功能已经实现了,下面需要完成的是print(t1)和直接调用t1均显示结果,那就需要重写__str__()和__repr__()魔法方法完成。

    def __str__(self):
        return self.prompt
    __repr__ = __str__

    来我们加上运行看下效果

    >>> import time as t
    >>> class MyTimer():
        def start(self):
            self.start = t.localtime()
            print("计时开始。。。")
        def stop(self):
            self.stop = t.localtime()
            self.__calc()
            print("结束计时。。。")
        def __calc(self):
            self.lasted = []
            self.prompt ="总共运行了"
            for index in range(6):
                self.lasted.append(self.stop[index] - self.start[index])
                self.prompt += str(self.lasted[index])
            print(self.prompt)
        def __str__(self):
            return self.prompt
        __repr__ = __str__
    
        
    >>> t1 = MyTimer()
    >>> t1.start()
    计时开始。。。
    >>> t1.stop()
    总共运行了000007
    结束计时。。。
    >>> t1
    总共运行了000007

    很不错的,但是,如果用户不按常理出牌,直接调用t1,那就报错了

    >>> t1 = MyTimer()
    >>> t1
    Traceback (most recent call last):
      File "<pyshell#57>", line 1, in <module>
        t1
      File "C:Python36libidlelib
    pc.py", line 617, in displayhook
        text = repr(value)
      File "<pyshell#51>", line 17, in __str__
        return self.prompt
    AttributeError: 'MyTimer' object has no attribute 'prompt'

    来我们先分析下,当直接执行t1的时候,python会调用__str__()魔法方法,但他却没有prompt属性。prompt属性在__calc()方法就没有被调用到,所以也就没有prompt属性的定义了。

    需要解决这个问题,需要用到在类里用到最多的方法__init__(),所有属于实例对象的变量只要在这里先定义,就不会出现这样的问题了

    >>> import time as t
    >>> class MyTimer():
        def __init__(self):
            self.prompt = '未开始计时'
            self.lasted = 0
            self.start = 0
            self.stop = 0
        def start(self):
            self.start = t.localtime()
            print("计时开始。。。")
        def stop(self):
            self.stop = t.localtime()
            self.__calc()
            print("结束计时。。。")
        def __calc(self):
            self.lasted = []
            self.prompt ="总共运行了"
            for index in range(6):
                self.lasted.append(self.stop[index] - self.start[index])
                self.prompt += str(self.lasted[index])
            print(self.prompt)
        def __str__(self):
            return self.prompt
        __repr__ = __str__
    
        
    >>> t1 = MyTimer()
    >>> t1
    未开始计时
    >>> t1.start()
    Traceback (most recent call last):
      File "<pyshell#71>", line 1, in <module>
        t1.start()
    TypeError: 'int' object is not callable

    这里跑出的错误,异常是:

    TypeError: 'int' object is not callable。在调用start()方法的时候报错,看一下是不是在__init__()方法里定义的self.start的变量和类中的方法名属性同名,属性会被覆盖方法。所以这就是问题所在,那就修改过来吧,吧self.start和self.stop改成self.begin和self.end,这样程序就没有问题了,但是现实时间为000007这样还是不太人性化,然后我们需要哪找年月日,值为0时不显示的原则,让人看着舒服
    >>> import time as t
    >>> class MyTimer():
        def __init__(self):
            self.unit =['','','','小时','分钟','']
            self.prompt = '未开始计时'
            self.lasted = []
            self.begin = 0
            self.end = 0
        def start(self):
            self.begin = t.localtime()
            print("计时开始。。。")
        def stop(self):
            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])
                self.prompt += (str(self.lasted[index]) + self.unit[index])
            print(self.prompt)
        def __str__(self):
            return self.prompt
        __repr__ = __str__
    
        
    >>> t1 = MyTimer()
    >>> t1.start()
    计时开始。。。
    >>> t1.stop()
    总共运行了0年0月0天0小时0分钟5秒
    结束计时。。。

    看似可以了,在加上一些温馨提示的就很好了,总程序

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

    结果:

    >>> t1 = MyTimer()
    >>> t1
    未开始计时
    >>> t1.stop()
    提示:请先调用start()开始计时
    >>> t1.start()
    计时开始。。。
    >>> t1
    提示;请先调用stop()结束计时
    >>> t1.stop
    <bound method MyTimer.stop of 提示;请先调用stop()结束计时>
    >>> t1.stop()
    总共运行了1分钟
    结束计时。。。
    >>> t1
    总共运行了1分钟>>> t2 = MyTimer()
    >>> t2.start()
    计时开始。。。
    >>> t2.stop()
    总共运行了5秒
    结束计时。。。
    >>> t2
    总共运行了5秒
    >>> t1+t2
    '总共运行了1分钟'
     
  • 相关阅读:
    二叉排序树 常用函数小结
    二叉树的应用:二叉排序树的删除
    剑指 Offer 32
    剑指 Offer 32
    剑指 Offer 68
    剑指 Offer 28. 对称的二叉树 做题小结
    正则表达式不要背
    剑指 Offer 55
    LeetCode226. 翻转二叉树 做题小结
    Tools | 编程IED/编译器
  • 原文地址:https://www.cnblogs.com/pinpin/p/9905980.html
Copyright © 2020-2023  润新知