Python中的__repr__和__str__

1. __repr__的作用

输出实例对象时,其内容由__repr__的返回值决定

举个例子吧,通俗易懂

class Test:
    def __repr__(self):
        return '铁锤'

t = Test()
print(t)  # 铁锤

可以看到,当打印实例对象的时候,打印的结果就是__repr__的返回值。而我们如果不定义__repr__则会默认使用object__repr__函数,返回的东西大家应该也都很清楚了,像下面这样的:

<__main__.Test object at 0x000002004AD16D00>

2. 实例对象接收的对象究竟是谁?

从上面的例子看起来,实例对象t接收的好像就是__repr__的返回值,那么他就应该是一个字符串啊;打印他的类型看一下:

print(t)  # 铁锤

print(type(t))  # class '__main__.Test'>

这里python告诉我们t的值虽然是一个字符串铁锤,但是他确实是一个实例对象。

那这不就矛盾了么,到底怎么回事呢?

我在文章Python 中的 __new__中提到过,实例对象最终接收的是类中__new__(即元类中__call__)的返回值。那么为什么打印出来的是__repr__的返回值呢?

接着往下看,做两个测试就懂了
测试一

class Test:
    def __new__(cls):
        return '砖头'

    def __repr__(self):
        return '铁锤'

t = Test()
print(t)  # 砖头
print(type(t))  # <class 'str'>

由上面这个例子可以看到,实例对象t接受的确确实实是__new__的返回值,无论是数值还是类型都对的上。(改成其他类型一样)

因此由上面这个例子可以断定:实例对象接收的是__new__的返回值


文章中对于id()函数和内存存储的研究讲过,要想判断python中两个变量到底指的是不是一个东西,就用id看一下他的内存地址情况就晓得了。

测试二

class Test:
    def __repr__(self):
        return '铁锤'

t = Test()
print(t)  # 铁锤
print(t.__repr__())  # 铁锤
print(id(t))  # 2115012947200
print(id(t.__repr__()))  # 2115012857168
print(id('铁锤'))  # 2115012857168

诶,是不是秒懂?其实当你打印实例对象的时候,python调用的其实是实例对象.__repr__(),因此其实是调用了实例对象t的__repr__方法,因此打印的结果和__repr__的返回值相同,但是t确实__new__返回的实例对象。

可以再用is来判断一下

print(t is t.__repr__())  # False
print('铁锤' is t.__repr__())  # True	

3. 结论

打印实例对象的时候,其实python真正执行的语句是print(实例对象.__repr__());因此打印的结果其实是__repr__的返回值,而实例对象接收的是__new__的返回值


4. __str__的作用

如果你理解了__repr__的作用以后,你就理解了__str__的作用了。

即这两个成员的作用是一模一样的,只不过__str__要更猛一点,当你的类中同时重写了__str____repr__后,那么当你打印实例对象的时候,python底层会优先执行实例对象.__str__()

class Test:
    def __repr__(self):
        return '铁锤'
    
    def __str__(self):
        return '砖头'

t = Test()

# 等效于 print(t.__str__())
print(t)  # 砖头

通过上面这个例子可以看到,输出的是__str__的返回值(__repr__没抢过__str__)。


那么__str____repr__有什么区别呢?
有些教程中会说__str__是面向用户的,__repr__是面向程序员的。
还是看两个例子
例子一:

In [12]: class Test:
    ...:     def __repr__(self):
    ...:         return '铁锤'
    ...:
    ...:     def __str__(self):
    ...:         return '砖头'
    ...:

In [13]: t = Test()

In [14]: t
Out[14]: 铁锤

In [15]: print(t)
砖头

例子二:

class Test:
    def __repr__(self):
        return '铁锤'
    
    def __str__(self):
        return '砖头'

t = Test()

还是这段代码,我们打开cmd,cd到这个py文件所在的路径以后,进入python环境

>>> from test import Test
>>> t = Test()
>>> t
铁锤
>>> print(t)
砖头

因此__repr____str__的区别就是:
当打印的时候python优先调用print(实例对象.__str__());而当在交互式界面直接敲实例对象的时候,python底层执行的其实是实例对象.__repr__()


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值