Python的魔法方法(完整示例):__str__和__repr__

提要

  • __repr____str__是python的两个魔法方法,更多的魔法方法可以参考 A Guide to Python’s Magic Methods
  • str()repr()都是python的内置函数,分别调用__repr__()__str__()

例子

  1. 通常情况下,直接输出某个实例化对象,本意往往是想了解该对象的基本信息,例如该对象有哪些属性,它们的值各是多少等等。但默认情况下,我们得到的信息只会是<__main__.类名+object at+内存地址>,对我们了解该实例化对象帮助不大,示例如下:

    class Student:
        def __init__(self, name, id):
            self.name = name
            self.id = id
            
    stu = Student("A", 1)
    print(stu)
    print(str(stu))
    print(repr(stu))
    
    ## 输出
    <__main__.Test object at 0x034664F0>
    <__main__.Test object at 0x034664F0>
    <__main__.Test object at 0x034664F0>
    
  2. 那么就需要我们自定义输出实例化对象的信息,通过重写__str__()或者__repr__()即可。

    class Student:
        def __init__(self, name, id):
            self.name = name
            self.id = id
    
        def __str__(self): # 重写__str__()方法,让其返回实例信息<name, id>
            return "<%s, %s>" % (self.name, self.id)
    
    stu = Student("A", 1)
    print(stu)
    print(str(stu))
    print(repr(stu))
    
    ## 输出
    <A, 1>
    <A, 1>
    <__main__.Test object at 0x02FB64F0>
    
  3. 上面重写了魔法方法__str__(),可以看到print(stu)print(str(stu))的打印结果已经是我们想要看到的实例信息了,可是print(repr(stu))的打印结果还是<__main__.类名+object at+内存地址>,现在我们重写__repr__()

    class Student:
        def __init__(self, name, id):
            self.name = name
            self.id = id
    
        def __repr__(self):  # 重写__repr__()方法,让其返回实例信息<name, id>
            return "<%s, %s>" % (self.name, self.id)
        ## 或者在上一个代码块__str__()的重写后加上下面的语句,即把__str__()的重写赋给__repr__()
        # __repr__ = __str__
    
    stu = Student("A", 1)
    print(stu)
    print(str(stu))
    print(repr(stu))
    
    ## 输出
    <A, 1>
    <A, 1>
    <A, 1>
    

关系

  1. 从上面的例子可以看出__str__方法其实调用了__repr__方法。

  2. 下面是Alex Martelli对于__str____repr__区别的解释:

    Other crucial tidbits to know: __str__ on a built-on container uses the __repr__, NOT the __str__, for the items it contains. And, despite the words on the subject found in typical docs, hardly anybody bothers making the __repr__ of objects be a string that eval may use to build an equal object (it’s just too hard, AND not knowing how the relevant module was actually imported makes it actually flat out impossible).

    So, my advice: focus on making __str__ reasonably human-readable, and __repr__ as unambiguous as you possibly can, even if that interferes with the fuzzy unattainable goal of making __repr__'s returned value acceptable as input to __eval__!

    • __str__目的是可读性好,面向用户的。
    • __repr__目的是更加正式清晰,面向开发者的。

使用

  1. 以下是来自bitoffdev 对于strrepr两者区别的更直观的回答,可以看出str(today)打印的结果普通人也容易看懂,而repr(today)打印的结果却没这么容易读取需要的信息。

    >>> import datetime
    >>> today = datetime.datetime.now()
    >>> str(today)
    '2020-06-02 21:45:48.335842'
    >>> repr(today)
    'datetime.datetime(2020, 6, 2, 21, 45, 48, 335842)'
    
  2. 当需要把实例对象的信息添加到列表或者字典中打印时,必须要重写__repr__()

    class Student:
        def __init__(self, name, id):
            self.name = name
            self.id = id
    
        def __str__(self):  # 重写__str__()方法,让其返回实例信息<name, id>
            return "<%s, %s>" % (self.name, self.id)
        # 把__str__()的重写赋给__repr__(),相当于重写__repr__()
        __repr__ = __str__
    
    li = list()
    li.append(Student("A", 1))
    li.append(Student("B", 2))
    print(li)
    print(str(li))
    print(repr(li))
    
    ## 输出
    [<A, 1>, <B, 2>]
    [<A, 1>, <B, 2>]
    [<A, 1>, <B, 2>]
    

    如果不把__str__()的重写赋给__repr__(),则会输出以下结果:

    [<__main__.Student object at 0x029764F0>, <__main__.Student object at 0x02976430>]
    [<__main__.Student object at 0x029764F0>, <__main__.Student object at 0x02976430>]
    [<__main__.Student object at 0x029764F0>, <__main__.Student object at 0x02976430>]
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值