32.Python进阶_魔法方法__str__和__repr__方法

当我们使用print()这个内置函数之后,给他传入一个对象,那么这个时候实际触发对象的__str__,将该方法的返回内容直接输出到控制台;

在交互环境中,输入对象,返回__repr__方法中返回的对象;

使用场景:

很多时候我们编写了一个类,在将它的实例在终端上打印或查看的时候,我们往往会看到一个不太满意的结果。

>>> class Car:
...     def __init__(self, color, mileage):
...             self.color = color
...             self.mileage = mileage
...
>>> my_car = Car('red', 37281)
>
>>> print (my_car)   #使用print输出
<__main__.Car object at 0x000001BEDBDDEAC8>

>>> my_car  #使用直接输出
<__main__.Car object at 0x000001BEDBDDEAC8>

类默认转化的字符串基本没有我们想要的一些东西,仅仅包含了类的名称以及实例的 ID (理解为 Python 对象的内存地址即可)。虽说这总比没有好,但确实是没什么用处啊。

所以,我们可能会手动打印对象的一些属性或者是在类里自己实现一个方法来返回我们需要的信息。

使用 str 实现类到字符串的转化

不用自己另外定义一个方法,和 JAVA 的 toString() 方法类似,你可以在类里实现__str__ 和 repr 方法从而自定义类的字符串描述,这两种都是比较 Pythonic 的方式去控制对象转化为字符串的方式。

下面我们通过做实验慢慢的来看这两种方式是怎么工作的。首先,我们先加一个 str 方法到前面的类中看看情况。

>>> class Car:
...     def __init__(self, color, mileage):
...         self.color = color
...         self.mileage = mileage
...     def  __str__(self):
...         return f'a {self.color} car'
...

当你重新打印和查看这个类的实例的时候,你会看到一个稍微不同的结果

>>> my_car = Car('red', 37281)
>>> print(my_car)
a red car

>>> my_car
<__main__.Car object at 0x000001BEDBDDEC18>

看 my_car 的时候的输出仍然和之前一样,不过打印 my_car 的时候返回的内容和新加的 str 方法的返回一致。类的 str 方法会在某些需要将对象转为字符串的时候被调用。比如下面这些情况

>>> print(my_car)
a red car
>>> str(my_car)
'a red car'
>>> '{}'.format(my_car)
'a red car'

有了 __str__ 这个方法,你就不用手动去打印对象的一些信息或者添加额外的方法去达到目的。类到字符串的转化使用 str 这种 Pythonic 的方式实现即可。

使用 repr 也有类似的效果

有的朋友可能发现,上面我们查看 my_car 对象的时候,输出的仍是类似 <main.Car object at 0x10b142128> 这样比较奇怪的结果。这是因为 Python 3 中一共有 2 中方式控制类到字符串的转化,第一种就是我们前面提到的 str 方法,另一个就是 repr 方法。后者的工作方式与前者类似,但是它被调用的时机不同。

这里有个简单的例子,同样是在之前的类上作改动

>>> class Car:
...     def __init__(self, color, mileage):
...         self.color = color
...         self.mileage = mileage
...     def  __str__(self):
...         return '__str__ for car'
...     def __repr__(self):
...         return '__repr__ for car'
...

我们通过下面的操作来感觉下什么时候调用 str ,什么时候调用的__repr__ 。

>>> my_car = Car('red', 37281)
>>> print(my_car)
__str__ for car
>>> '{}'.format(my_car)
'__str__ for car'
>>> my_car
__repr__ for car	

从上面可以看出,当我们查看对象的时候(上面的最后一个操作)调用的是 repr 方法。

str 和 repr 的差别

现在你可能在想,__str__ 和 __repr__ 的差别究竟在哪里,它们的功能都是实现类到字符串的转化,它们的特定并没有体现出用途上的差异。

带着这个这个问题,我们试着去 Python 的标准库中找找答案。我们就来看看 datetime.date 这个类是怎么在使用这两个方法的。

>>> today = datetime.date.today()
>>> today
datetime.date(2019, 4, 30)
>>> str(today)
'2019-04-30'
>>> repr(today)
'datetime.date(2019, 4, 30)'

因此,我们有个初步的答案。

str 的返回结果可读性强。

repr 的返回结果应更准确。

Python内置函数str和repr,format
  • 内置函数str转换一个对象时,触发对象对应__str__方法
  • 内置函数format处置对象时,触发对象对应__str__方法
  • 内置函数repr函数,触发对象的__repr__的方法

__str__和__repr__方法触发机制
在这里插入图片描述

结论:
  1. 我们可以使用 __str____repr__ 方法定义类到字符串的转化方式,而不需要手动打印某些属性或是添加额外的方法。
  2. 一般来说,__str__ 的返回结果在于强可读性,而 __repr__ 的返回结果在于准确性。
  • 如果类中没有str和repr方法则打印:<main.App object at 0x00000266BDFD2F60>
  • 如果类中同时存在str和repr方法则打印str方法的返回值
  • 如果类中存在其一,则打印该方法的返回值。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值