Python 中 __str__ 与 __repr__ 方法的区别与调用机制详解

许南星
许南星
发布时间:2026-10-14| 3人浏览过
原创

本文深入解析 Python 中 __str__ 和 __repr__ 两个魔术方法的定义与调用时机。通过对比内置类型与自定义类的行为,阐明 repr 作为正式表示在调试和交互环境中的优先级,以及 str 在用户友好输出中的作用。文章还探讨了当仅定义其中一个方法时的回退机制,以及字符串格式化、print 和调试器显示的具体调用逻辑,帮助开发者正确实现对象的可读性与可重现性。

引言:__str__ 与 __repr__ 的基本概念

在阅读关于将对象转换为字符串的章节时,接触到了 repr 函数。为了在深入掌握 Python 面向对象编程之前建立直观认知,这里从感性角度梳理 repr 与 str 这两个函数的核心区别。

Python 的全局函数 repr 和 str 分别映射到对象的 __repr__ 和 __str__ 方法调用。此外,当执行 str(obj) 或 print(obj) 操作时,以及在进行 Python 代码调试以查看对象状态时,系统会优先调用哪个方法?这正是本文旨在验证的关键点。

类比 Java 中 System.out.println(obj) 或字符串拼接 "hello" + obj 都会触发调用 Java 对象的 toString() 方法,我们需要探究 Python 中对应的机制是如何运作的。

官方定义:正式表示与非正式表示

参考某本 Python 入门书籍对 repr 和 str 的解释:

  1. repr: 提供 Python 对象的正式字符串表示形式(formal string representation)。
  2. str: 提供 Python 对象的非正式字符串表示形式(informal string representation),即可打印的字符串表示。

从字面含义来看, repr 代表“表示(representation)”,分为正式与非正式两种。表面上看,repr 似乎比 str 更为重要,因为它提供了更精确的对象信息。

内置类型的行为分析

对于 Python 内置对象,我们可以使用 repr、print 和 str 等函数进行转换。以 list 类型为例,其行为如下:


>>> repr([1,2])
'[1, 2]'
>>> print([1,2])
[1, 2]
>>> str([1,2])
'[1, 2]'

自定义类实验:仅定义 __str__ 的情况

然而,上述三个内置函数具体调用了 list 类的哪个内部方法并不直观。为了清晰说明这一点,定义一个自定义类进行实验是最有效的方式。测试环境为 IntelliJ IDEA,以下调试截图展示了 __str__ 和 __repr__ 几种不同定义组合下的表现。

情况一:仅定义了 __str__ 方法。

说明:在仅定义了 __str__ 方法的情况下:

  1. 调试器在代码行内显示对象时,展示的是 __str__ 的输出结果;但在变量窗口中查看变量详情时,显示的是默认的 __repr__ 输出结果。
  2. 函数 repr 始终坚持调用默认的 __repr__ 方法,即使未显式定义。
  3. 函数 str 转型操作明确调用了对象的 __str__ 方法。
  4. 函数 print 调用了对象的 __str__ 方法。

自定义类实验:仅定义 __repr__ 的情况

情况二:仅定义了 __repr__ 方法。

说明:在仅定义了 __repr__ 方法的情况下,可以看出 __repr__ 方法具有极高的优先级。它“垄断”了大部分调用场景,包括 repr、str 和 print 函数,甚至 IntelliJ 的调试显示也必须以 __repr__ 方法为核心。

  1. 在上述所有情况下,系统最终都调用了 __repr__ 方法,没有其他选择。

自定义类实验:同时定义两种方法

情况三:同时定义了 __repr__ 和 __str__ 方法。

说明:在同时定义了 __repr__ 和 __str__ 方法的情况下,__str__ 方法反而能“扳回一局”。除了明确的 repr 会调用 __repr__ 方法,以及调试时变量窗口中显示对象会调用 __repr__ 方法外,其他大多数场景下 __str__ 占优。具体表现如下:

  1. 使用 函数及 IntelliJ 调试时变量窗口显示变量,均调用 __repr__ 方法。
  2. IntelliJ 调试时行内显示变量,调用了 __str__ 方法。
  3. 执行 转型操作时,调用了对象的 __str__ 方法。这不能简单解释为“非正式”,而是用户友好的输出。
  4. 使用 打印对象时,调用 __str__ 来获取对象的输出字符串。

字符串格式化与拼接的特殊处理

另外,在格式化字符串时调用的对象方法与 print 时一致,例如以下格式化代码:


f1 = "%s" % t
f2 = "{}".format(t)

Python 不会像 Java 那样自动将字符串与对象进行拼接(即 Python 不知道像 Java 那样由字符串加上一个对象)。


"this is " + t #Java 中会展开为 "this is " + t.toString()

Python 会报以下错误:

TypeError: can only concatenate str (not "Test") to str

这表明这里的 + 号只能连接两个字符串。除非定义了 __add__ 和 __radd__ 方法,其对应关系分别为:


t = Test()
z1 = 'hello' + t #相当于 t.__radd__('hello')
z2 = t + 'hello' #相当于 t.__add__('hello')

Python 的 __xyz__ 机制也颇具特色。

以上就是 Python 的 __str__ 和 __repr__ 方法对比的详细内容,更多关于 Python __str__ 和 __repr__ 的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。