一、思考

当我们在Python中定义一个类的时候,如果我们通过print打印这个类的实例化对象,或者我们直接输入这个类实例化对象会返回怎么样的结果,如下代码:

>>> class People(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
...
>>> tom = People("Tom", 23)
>>> print(tom)
<__main__.People object at 0x00000000027A7160>
>>> tom
<__main__.People object at 0x00000000027A7160>
>>>

默认情况下,你得到的是一个字符串,其中包含类名和对象实例的id(这是CPython中对象的内存地址),其实有更加Pythonic的方式去控制不同情况下将对象进行转换为字符串,也就是控制其显示的结果内容。 我们把上面的代码进行更改的内容如下:

>>> class People(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
... def __str__(self):
... return f"people name is {self.name}"
...
>>> tom = People("Tom", 23)
>>> print(tom)
people name is Tom
>>> tom
<__main__.People object at 0x00000000021B7208>
>>>

str 是python的内置方法,并且当你在尝试去吧一个对象转换为一个字符串的时候怎么调用这个str方法,如我们进行如下操作时:

>>> class People(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
... def __str__(self):
... return f"people name is {self.name}"
...
>>> tom = People("Tom", 23)
>>> print(tom)
people name is Tom
>>> str(tom)
'people name is Tom'
>>> '{}'.format(tom)
'people name is Tom'
>>> tom
<__main__.People object at 0x00000000021E7208>
>>>

二、__str__ vs __repr__

在上面的代码中我们添加了str_方法之后,当我们将对象转换为字符串的时候都会调用str方法,并得到我们自己定义的内容,但是并没有影响到我们在python交互模式下直接输入对象的返回内容。其实
repr 和 str 其实是非常类似的,只不过用的场景不同,将上面的代码进行调整:

>>> class People(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
... def __str__(self):
... return f"people name is {self.name}"
... def __repr__(self):
... return f"__repr__: people name is {self.name}"
...
>>> tom = People("Tom", 23)
>>> print(tom)
people name is Tom
>>> str(tom)
'people name is Tom'
>>> '{}'.format(tom)
'people name is Tom'
>>> tom
__repr__: people name is Tom
>>>

其实这里也就验证了,在Python的交互模式下,检查一个对象,其实就是在调用对象的repr方法,还有一个你可能没有发现的地方就是当你在list,dict等容器中存储对象的时候,我们打印看到的都是repr的内容,我们把上面的tom存到列表里, 然后打印查看如下:

>>> print([tom])
[__repr__: people name is Tom]
>>>

为了验证我们到底应该怎么用这两个方法,毕竟这两个方法的作用还是非常类似的,我们可以通过Python标准库来验证一下,跟着标准库走总不会有错

>>> import datetime
>>> today = datetime.date.today()
>>> today
datetime.date(2019, 3, 5)
>>> str(today)
'2019-03-05'
>>> repr(today)
'datetime.date(2019, 3, 5)'
>>>

从这个Python标准库的用法,我们也能非常好的理解str方法其实就是为了返回一个人们容易理解的字符串类型的结果,而repr方法更偏向于程序员方便去调试,能从结果中看到更加有用的信息,它甚至包括完整的模块和类

三、Why Every Class Needs a repr

我们先看一下我们将我们上面代码的str方法去掉之后的结果:

>>> class People(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
... # def __str__(self):
... # return f"people name is {self.name}"
... def __repr__(self):
... return f"__repr__: people name is {self.name}"
...
>>> tom = People("Tom", 23)
>>> print(tom)
__repr__: people name is Tom
>>> str(tom)
'__repr__: people name is Tom'
>>> '{}'.format(tom)
'__repr__: people name is Tom'
>>> tom
__repr__: people name is Tom
>>>

从这里我们发现当当你把对象进行字符串转换的时候,就会先去找str方法,如果没有则再去找repr方法执行
所以还是建议在自己定义的类中都至少有一个repr方法,这样不管在上面情况下,你都能有一个对你来说有用的字符串返回结果,而不再是一个干巴巴的内存地址,所以在最后我们规范一下我们写一个Python类时的代码:

class People(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f'people name is {self.name}'
def __repr__(self):
return (f'{self.__class__.__name__}('
f'{self.name!r}, {self.age!r})')

在最后的repr的返回中我们用了!r 这个意味着我们要的repr(self.name) repr(self.age)而不是要str(self.name) str(self.age)的返回结果

Python Every Class Needs a __repr__的更多相关文章

  1. python中的__str__和__repr__方法

    如果要把一个类的实例变成 str,就需要实现特殊方法__str__(): class A(object): def __init__(self,name,age): self.name=name se ...

  2. 第8.15节 Python重写自定义类的__repr__方法

    一. 引言 前面两节分别介绍了Python类中的__str__和__repr__方法的作用和语法,所有新式类都支持这两个方法,因为object类实现了这两个方法,但实际上各位开发者在自定义类的过程中, ...

  3. Python中的魔法函数__repr__和__str__的实质性区别

    str 和 repr 方法:是自定义类的字符串描述,这两种都是比较 Pythonic 的方式去控制对象转化为字符串的方式. 调用这两个方法,返回的都是字符串.但是这两个方法又有一些区别 ** 1 两种 ...

  4. python 中的__str__ 和__repr__方法

    看下面的例子就明白了 class Test(object): def __init__(self, value='hello, world!'): self.data = value >> ...

  5. python 的特殊方法 __str__和__repr__

    __str__和__repr__ 如果要把一个类的实例变成 str,就需要实现特殊方法__str__(): class Person(object): def __init__(self, name, ...

  6. 浅谈python中__str__和__repr__的区别

    很多时候我们在创建一个类的时候,在终端打印类或者查看的时候一般都不会得到一个太满意的结果 class T: def __init__(self): self.color="red" ...

  7. Python中自定义类如果重写了__repr__方法为什么会影响到str的输出?

    这是因为Python3中,str的输出是调用类的实例方法__str__来输出,如果__str__方法没有重写,则自动继承object类的__str__方法,而object类的__str__方法是调用_ ...

  8. 利用Python特殊变量__dict__快速实现__repr__的一种方法

    在<第8.15节 Python重写自定义类的__repr__方法>.<Python中repr(变量)和str(变量)的返回值有什么区别和联系>.<第8.13节 Pytho ...

  9. Python基础学习笔记FromImooc.com

    1.list L = ['a','a','a','a','a','a3'] L[0] = a L[-1] = a3   添加新元素 L.append('paul') L.insert(-1,'Paul ...

随机推荐

  1. shell 脚本使用记录

    2019-03-26 需求是:因为遇到一些测试偶发性的出现,比如执行了20次会出一次错误,然后就顺手写了一个小脚本,用来判断执行了 n 次,是否出现错误.根据正则来匹配出substring value ...

  2. Altium Desgner软件,PCB设计中铺铜的作用

    PS原文出自http://mp.weixin.qq.com/s/5mLNXzCDm1hGOXiKNE8Ddg 问1:为何要铺铜? 答:一般铺铜有几个方面原因. 1.EMC.对于大面积的地或电源铺铜,会 ...

  3. 给有C或C++基础的Python入门 :Python Crash Course 4 操作列表 4.4 -- 4.5

    上接前一篇文章. 4.4 使用列表的一部分 一,切片 切边,顾名思义,就是处理列表的部分元素. 我们可以联系一下C++的一段语句:for(int i = 0; i < n-2; ++i) cou ...

  4. MongoError: Cannot update '__v' and '__v' at the same time,错误解决办法

    1.讲查询的结果,原封不动的插入到另一个表中,结果报错了:MongoError: Cannot update '__v' and '__v' at the same time,起初认为是mongodb ...

  5. BZOJ4738 : 汽水

    二分答案$mid$,若存在一条路径满足$|ave-k|<mid$,则答案至多为$mid-1$. 若$ave\leq k$,则$\sum(w-k)\leq 0$,且$\sum(k-w-mid)&l ...

  6. HBase 查询导致RegionServer OOM故障复盘

    背景:我司作为某运营商公司的技术咨询公司,发现有第三方开发公司在使用HBase 1.1.2 (HDP 2.4.2.258版本)一段时间使用正常后,从某一天开始报OOM,从而导致RegionServer ...

  7. poj3061 Subsequence(尺取法)

    https://vjudge.net/problem/POJ-3061 尺取发,s和t不断推进的算法.因为每一轮s都推进1所以复杂度为O(n) #include<iostream> #in ...

  8. 部署Bookinfo示例程序详细过程和步骤(基于Kubernetes集群+Istio v1.0)

    部署Bookinfo示例程序详细过程和步骤(基于Kubernetes集群+Istio v1.0) 部署Bookinfo示例程序   在下载的Istio安装包的samples目录中包含了示例应用程序. ...

  9. 安装istio v1.0 详细过程和步骤

      创建 istio 目录 [root@centos-110 ~]# mkdir istio [root@centos-110 ~]# cd istio   方案一: # 去下面的地址下载压缩包  # ...

  10. ASP.NET WebAPI数据传输安全HTTPS实战项目演练

    一.课程介绍 HTTPS是互联网 Web 大势所趋,各大网站都已陆续部署了 HTTPS .  全站HTTPS时代,加密用户与网站间的交互访问,在客户端浏览器和Web服务器之间建立安全加密通道,一般情况 ...