首页 > 其他分享 >__str__和__repr__之间的区别是什么?

__str__和__repr__之间的区别是什么?

时间:2023-10-25 20:45:19浏览次数:27  
标签:__ Python repr 默认 实现 str

内容来自 DOC https://q.houxu6.top/?s=__str__和__repr__之间的区别是什么?

在Python中,__str____repr__的区别是什么?


Alex Martelli对Python中的__str____repr__进行了总结,但令人惊讶的是,他的回答过于简洁。

首先,让我重申一下Alex在他的帖子中的主要观点:

  • 默认实现是无用的(很难想象有一个不是这样的,但是是的)
  • __repr__的目标是明确无误
  • __str__的目标是易于阅读
  • 容器的__str__使用包含的对象的__repr__

默认实现是无用的

这主要是因为Python的默认实现通常都是相当有用的。然而,在这种情况下,对于__repr__来说,有一个默认的实现会是这样的:

return "%s(%r)" % (self.__class__, self.__dict__)

这将会变得非常危险(例如,如果对象相互引用,就很容易陷入无限递归)。因此Python放弃了这个默认实现。需要注意的是,有一个默认实现是真实的:如果定义了__repr__,但没有定义__str__,那么对象的行为将类似于__str__=__repr__

这意味着,简单地说:几乎所有你实现的对象都应该有一个可用的、用于理解对象的__repr__。实现__str__是可选的:如果你需要“漂亮的打印”功能(例如,被报告生成器使用),则需要这样做。

__repr__的目标是明确无误

我直接说出来——我不相信调试器。我不太知道如何使用任何调试器,也从未认真地使用过。此外,我相信调试器的根本性质——我发现大多数失败的调试都发生在很久以前,在一个遥远的星系里。这意味着我确实相信,以虔诚的态度相信日志记录。日志记录是任何可靠地“烧掉”服务器系统的命脉。Python使得记录日志变得容易:只需要一些针对项目特定的包装器,你所需要的只是

log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)

但你必须完成最后一步——确保你实现的每个对象都有一个有用的repr,这样像那样的代码就可以正常工作。这就是为什么“eval”的概念出现了:如果你有足够的信息,以至于eval(repr(c))==c,那么这意味着你对c的所有事情都知道。如果这足够简单,至少在模糊的方式下,就去做吧。如果不是,请确保无论如何你都有关于c的足够信息。我通常使用类似eval的格式:"MyClass(this=%r,that=%r)" % (self.this,self.that)。它并不意味着你可以实际构造MyClass,或者这些是正确的构造函数参数——但它是表达“这是关于此实例你需要知道的一切”的有用形式。

注意:我在上面的代码中使用了%r,而不是%s。你总是想在__repr__的实现中使用repr() [或等效的%r格式化字符],否则你就会破坏repr的目标。你想要能够区分MyClass(3)MyClass("3")

__str__的目标是易于阅读

具体来说,它并不是旨在明确无误的——请注意str(3)==str("3")。同样地,如果你实现了一个IP抽象,让它的str看起来像是192.168.1.1是完全可以的。当你实现一个日期/时间抽象时,str可以是"2010/4/12 15:35:22",等等。目标是以一种用户(而不是程序员)愿意阅读的方式来表示它。删除无用的数字,假装成其他类——只要它支持可读性,就是改进。

容器的__str__使用包含的对象的__repr__

这似乎令人惊讶,不是吗?它有点,但是如果它使用它们的__str__会是什么样子呢?
不太多。具体来说,容器中的字符串会很容易干扰其字符串表示形式。面对歧义时,请记住,Python抵制猜测的诱惑。如果您想在打印列表时获得上述行为,只需使用以下代码:

print("[" + ", ".join(lst) + "]")

(您可能还可以想出如何处理字典)。

总结

对于您实现的任何类,请实现__repr__方法。这应该是自然而然的事情。如果您认为拥有一个倾向于可读性的字符串版本是有用的,请实现__str__方法。

标签:__,Python,repr,默认,实现,str
From: https://www.cnblogs.com/xiaomandujia/p/17788079.html

相关文章

  • 解决VirtualBox虚拟机与主机之间无法复制粘贴的问题
    目录1、开启共享粘贴板和拖放功能2、勾选使用主机IO缓存3、勾选*.vdi为固态驱动器4、安装virtualBox增强功能(重要)5、附加步骤1、开启共享粘贴板和拖放功能首先确保虚拟机系统关闭即没有运行,接着在虚拟机软件VirtualBox选择对应设置的虚拟机系统,然后右侧点击设置(Settings)......
  • 10 25
    分页思路SELECT*fromsys_userlimit0,2;--第一页--(2-1)*2=2SELECT*fromsys_userlimit2,2;--第二页--(3-1)*2=4SELECT*fromsys_userlimit4,2;--第三页--结论:limit第一个参数=(pageNum-1)*pageSize//分页查询//接口路径:/use......
  • vue的通讯方式
    vue中通讯方式propsemitv-modelrefsprovide/injecteventBusVuex/pinia(vue3)1.Props方式父组件以数据绑定的形式声明要传递的数据,子组件通过defineProperty()方法创建props对象,即可拿到父组件传来的数据,该方式用于父传子。 父组件的template中:<!--list是我们要......
  • NOIP2023模拟2联测23 C. 负责
    NOIP2023模拟2联测23C.负责目录NOIP2023模拟2联测23C.负责题目大意思路code题目大意给你\(n\)个区间\([l_i,r_i]\),每个区间有个\(w_i\)。如果两个区间有交集(包括端点)那么两个区间就可以连边,形成一个图。现在需要你删除一些区间,使得每个区间大小不超过\(k\)。......
  • 显式关键字是什么意思?
    内容来自DOChttps://q.houxu6.top/?s=显式关键字是什么意思?在C++中,explicit关键字是什么意思?编译器被允许进行一次隐式转换以解析参数为函数。这意味着编译器可以使用带有单个参数的构造函数将类型转换为另一个类型,以获得正确的参数类型。以下是具有可用于隐式转换的构造......
  • 堆栈模拟队列
    堆栈模拟队列题目大意PTA上的一道题,详题见文末。设已知有两个堆栈S1和S2,请用这两个堆栈模拟出一个队列Q。输入:32A1A2A3A4A5DA6DA7DA8DDDDT输出:ERROR:Full1ERROR:Full23478ERROR:Empty思路最开始设想的是将长度小的栈作为存储栈,长度大......
  • 10月25每日打卡
    下载commons-csv-1.8.jar网址:commons-csv-1.8.jar下载及Maven、Gradle引入代码,pom文件及包内class-时代Java(nowjava.com) importjava.io.*;importjava.util.ArrayList;importjava.util.List;importjava.util.Random;publicclassMathExercisesCSV{publicsta......
  • 2023.10.25——每日总结
    学习所花时间(包括上课):9h代码量(行):0行博客量(篇):1篇今天,上午学习,下午学习;我了解到的知识点:1.java断言,代码区域等明日计划:学习......
  • 如何提高系统的可用性/高可用
    提高系统可用性常用的一些方法,有缓存、异步、重试、幂等、补偿、熔断、降级、限流。缓存缓存的速度,比数据库快很多,添加缓存是简单有效的做法。注意缓存与数据库的一致性,数据表记录变更时记得处理缓存。Redis缓存的示例,详情见:https://blog.csdn.net/sinat_32502451/article/det......
  • 经典闭包
     先看常见的问题internalclassProgram{staticvoidMain(string[]args){varactions=GetSomeAction();for(inti=0;i<actions.Count;i++)actions[i]();}staticList<Action>GetSomeAction(){......