浅谈python中__str__和__repr__的区别
很多时候我们在创建一个类的时候,在终端打印类或者查看的时候一般都不会得到一个太满意的结果
class T:
def __init__(self):
self.color="red"
self.count = 2
t = T()
t
>>> <T object at 0x0000000003444E10>
print(t)
>>> <T object at 0x0000000003444E10>
类转化为字符串,直接打印结果一般都不是我们想要的东西,仅仅包含了类的名称以及实例的 ID (理解为 Python 对象的内存地址即可),例如<T object at 0x0000000003444E10> ,这样类默认转化为字符串根本不能得到我们想要的关于属性信息等的相关东西,只能通过手动打印才能进一步获取到更多的信息,例如print(t.color)
使用 __str__ 实现类到字符串的转化
不用自己另外的定义方法,和java的toString的方法类似,可以在类里面实现__str__和__repr__方法,从而自已定义类的字符串描述,下面具体看看这两种方式是怎么工作的。
首先,我们先加一个 __str__ 方法到前面的类中看看情况。
class T:
def __str__(self):
return self.color+"__str__"
def __init__(self):
self.color="red"
self.count = 2
t = T()
t
>>> <T object at 0x0000000003444E10>
print(t)
>>> red__str__
查看 t的时候的输出仍然和之前一样,输出内存地址信息,不过打印 t的时候返回的内容和新加的 __str__ 方法的返回一致。类的 __str__ 方法会在某些 需要将对象转为字符串的时候被调用。
比如下面这些情况,需要将对象转为字符串
print(t)
print(str(t))
print("{}".format(t))
使用 __repr__ 也有类似的效果
会发现,在使用__str__方法的时候,直接在终端查看t对象的时候,输出的时候仍然是内存地址,这是因为在python3中有两种方式控制对象转字符串,第一种就是__str__,第二种就是__repr__,两种的工作方式大体相同,只是调用的时机不同。下面通过一个简单的例子看看__repr__方法
class T:
def __repr__(self):
return self.color+"__repr__"
def __str__(self):
return self.color+"__str__"
def __init__(self):
self.color="red"
self.count = 2
t = T()
t
>>> red__repr__
print(t)
>>> red__str__
print(str(t))
>>> red__str__
print("{}".format(t))
>>> red__str__
print(str(["d","f",t]))
>>> ['d', 'f', red__repr__]
通过如上的例子可以看出,当直接查看对象的时候调用的是__repr__方法,对象需要转字符串的时候调用的是__str__方法,但是当字典列表等容器的时候调用的还是__repr__方法
如果我们需要显示的指定以何种方式进行类到字符串的转化,我们可以使用内置的 str() 或 repr() 方法,它们会调用类中对应的双下划线方法。除了字典、列表等作为容器的时候print(str(["d","f",t])),虽然调用的是str()方法,可是容器是列表,所以对象t转为字符串时调用的就是__repr__
__str__ 和 __repr__ 的差别
那么他们的区别具体的在哪里,带着这个问题我们python的标准库, 其中datetime.date 这个类是怎么在使用这两个方法的。
import datetime
today = datetime.datetime.today()
print(str(today))
>>> 2019-10-20 20:59:47.003003
print(repr(today))
>>> datetime.datetime(2019, 10, 20, 20, 59, 47, 3003)
__str__ 的返回结果可读性强。也就是说,__str__ 的意义是得到便于人们阅读的信息,就像上面的 '2019-10-20 20:59:47.003003' 一样。
__repr__ 的返回结果应更准确。怎么说,__repr__ 存在的目的在于调试,便于开发者使用。将 __repr__ 返回的方式直接复制到命令行上,是可以直接执行的。
为什么每个类都最好有一个 __repr__ 方法
如果你想保证每个类到字符串都有一个有效的自定义转换方式,你需要重写__str__或者__repr__中的一个方法,如果没有写__str__方法,python就会去找__repr__方法,所以至少添加一个
class T:
def __repr__(self):
return (self.color)
def __init__(self,color):
self.color = color
t = T("red")
print(t)
>>> red
t
>>> red
print(str(t))
>>> red
实现了 __repr__ 方法后,当我们查看类的实例或者直接调用 repr() 方法,就能得到一个比较满意的结果了。打印或直接调用str()等类转字符串的操作都会得到相同的结果,因为__str__的默认实现就是调用__repr__方法。
- 我们可以使用__str__ 和 __repr__中的任意一个方法定义类到字符串的转化方式,不需要手动的打印某些属性和一些额外的信息
- 一般来说__str__的可读性更强,而__repr__的返回结果更具有准确性,更加的适合开发者
- 我们在写类的时候,最好至少添加一个__repr__方法,来保证类到字符串的转换具有自定义的有效性,__str__是可选的,因为在默认情况下,__Str__方法默认实现调用的是__repr__方法,所以在对象转字符串时候,找到底层str方法之后,会调用重写的__repr__方法
也就是说,
直接查看字符串的时候调用的是__repr__方法;
对象在转字符串的时候:如果容器是字典或者列表调用的是__repr__方法;如果是其他情况则默认调用的是底层的__Str__方法。__str__如果被重写调用的则是重写之后__Str__,就和__repr__没有关系了,如果没有被重写,则调用的是底层__str__方法,底层方法默认实现方式是调用了__repr__ 方法,之后查看__repr__是否被重写,重写则调用重写之后的,否则调用底层的__repr__,最后执行转为字符串
如果打印str(t)则默认调用的是__str__,如果直接打印repr(t)则默认调用的是__repr__方法
浅谈python中__str__和__repr__的区别的更多相关文章
- python中__str__与__repr__的区别
__str__和repr __str__和__repr__都是python的内置方法,都用与将对象的属性转化成人类容易识别的信息,他们有什么区别呢 来看一段代码 from math import hy ...
- Python中__str__和__repr__的区别
Python有一个内置的函数叫repr,它能把一个对象用字符串的形式表达出来以便辨认,这就是“字符串表示形式”.repr就是通过__repr__这个特殊方法来得到一个对象的字符串表示形式.如果没有实现 ...
- 浅谈Python 中 __getattr__与__getattribute__的区别
__getattr__与__getattribute__均是一般实例属性截取函数(generic instance attribute interception method),其中,__getatt ...
- 浅谈Python中的深浅拷贝的区别
深.浅拷贝总结 深拷贝 拷贝可变数据类型,如列表容器: a = [1, 2, [3, 4]] b = copy.deepcopy(a) a 与 b 所指的列表容器的空间地址不一致,即 id(a) != ...
- 转 浅谈C++中指针和引用的区别
浅谈C++中指针和引用的区别 浅谈C++中指针和引用的区别 指针和引用在C++中很常用,但是对于它们之间的区别很多初学者都不是太熟悉,下面来谈谈他们2者之间的区别和用法. 1.指针和引用的定义和性 ...
- 浅谈 HTTP中Get与Post的区别
浅谈 HTTP中Get与Post的区别 存在的误区 有人说 HTTP 协议下的 Get 请求参数长度是有大小限制的,最大不能超过XX,而 Post 是无限制的,看到这里,我想他们定是看多了一些以讹传讹 ...
- 浅谈Java中set.map.List的区别
就学习经验,浅谈Java中的Set,List,Map的区别,对JAVA的集合的理解是想对于数组: 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型),JAVA集合可以存储和操 ...
- python中__str__与__repr__
(1)背景 python中,对于类(自定义类)的实例对象的默认显示既没有太大用处,也不美观.比如: class adder: def __init__(self,value=0): self.data ...
- 浅谈python中得import xxx,from xxx import xxx, from xxx import *
在python中import跟from import都是用来导入的,但是导入的机制不同 1.import xxx:导入模块,或者文件夹,对于调用模块或者文件夹中子模块的变量或者函数,需要使用" ...
随机推荐
- PLL
PLL(Phase Locked Loop): 为锁相回路或锁相环,用来统一整合时脉讯号,使内存能正确的存取资料.PLL用于振荡器中的反馈技术. 许多电子设备要正常工作,通常需要外部的输入信号与内部的 ...
- xampp 软件端口占用
参考链接: https://jingyan.baidu.com/album/48b558e3ede7747f39c09a55.html?picindex=1 查看端口占用情况 参考资料: https: ...
- HttpRunner接口自动化框架的使用
简介: HttpRunner 是一款面向 HTTP(S) 协议的通用测试框架,只需编写维护一份 YAML/JSON 脚本,即可实现自动化测试.性能测试.线上监控.持续集成等多种测试需求. HttpRu ...
- sql根据字符将一行拆成多行
SELECT B.value FROM ( SELECT [value] = CONVERT(xml,'<root><v>' + REPLACE('A,C,D', ',', ' ...
- Vue+ElementUI重置表单数据至初始值
https://blog.csdn.net/linjingke32/article/details/99446403
- 一些关于网页标题的动态js特效
1.当转换页面时,标题改变 <script> document.addEventListener('visibilitychange',function(){ if(document.vi ...
- mysql和oracle建表语句以及数据类型的区别
1.mysql和oracle建表语句的区别 mysql DROP TABLE IF EXISTS `order`;CREATE TABLE `order` ( `id` int(11) NOT NU ...
- C++ - cpprestsdk
Windows 安装方法: CMake 1.32+,生成过程会将 vcpkg 下载好,配置到系统环境变量,然后用 vcpkg 安装依赖库(github 上有列出需要的依赖库). Github 上的示例 ...
- PMP概略学习上--基本思想和概念
1 前言 花了10天左右的时间,对PMP(Project Management Professional,项目管理专业人士)考试认证做了一个概略学习.此次学习的目的是整体了解项目管理知识,并不是以考试 ...
- 刷题3. Longest Substring Without Repeating Characters
一.题目 Longest Substring Without Repeating Characters,具体请自行搜索. 这个题目,我看了一下,经过一番思考,我觉得实现起来不是很复杂. 但要做到bug ...