对于自定义 Python 类,哪个 __repr__ 更好?

Posted

技术标签:

【中文标题】对于自定义 Python 类,哪个 __repr__ 更好?【英文标题】:Which is a better __repr__ for a custom Python class? 【发布时间】:2011-09-15 04:47:56 【问题描述】:

__repr__ 函数似乎有不同的返回方式。

我有一个类 InfoObj 存储了许多东西,其中一些我不特别希望该类的用户自己设置。我认识到 python 中没有任何东西受到保护,他们可以直接潜入并设置它,但似乎在 __init__ 中定义它使得有人更有可能看到它并认为只需将它传入就可以了。

(示例:当验证函数确定对象已完全填充时由验证函数设置的布尔值,以及在存储足够信息时从其他值计算的值...例如 A = B + C ,因此一旦设置了 A 和 B,则计算 C 并将对象标记为 Valid=True。)

那么,考虑到所有这些,设计 __repr__ 输出的最佳方式是什么?

    bob = InfoObj(Name="Bob")
    # Populate bob.

    # Output type A:
    bob.__repr__()
'<InfoObj object at 0x1b91ca42>'

    # Output type B:
    bob.__repr__()
'InfoObj(Name="Bob",Pants=True,A=7,B=5,C=2,Valid=True)'

    # Output type C:
    bob.__repr__()
'InfoObj.NewInfoObj(Name="Bob",Pants=True,A=7,B=5,C=2,Valid=True)'

... C 类型的要点是不要愉快地将我在 C++ 中设置为“私有”的所有东西作为构造函数的参数,并让使用该类的队友使用接口函数设置它,即使这对他们来说是更多的工作。在这种情况下,我将定义一个不包含某些内容的构造函数,以及一个稍微难以注意到的单独函数,用于__repr__

如果有什么不同,我打算使用它们的__repr__ 输出将这些python 对象存储在数据库中,并使用eval() 检索它们,至少除非我想出更好的方法。队友手动创建完整对象而不是通过适当的接口函数的后果只是一种类型的信息检索可能会不稳定,直到有人弄清楚他做了什么。

【问题讨论】:

顺便说一句,语法很仓促,可能有点粗糙。我没有设计所有三个,然后复制粘贴它们的实际输出。 :) 您可以使用pickle将您的对象存储在数据库中 “对开发人员(例如您)识别对象有用的东西”,无论是什么。它不需要公开所有数据或者是可逆的。这里eval()的使用是... ick @Brian No. 这根本不是要求。虽然这是基本类型(数字、字符串等)的工作方式,但没有合同行为。考虑:eval(repr(re.compile("doesn't work"))),其中re 是正则表达式模块。 @pst 好吧,所以我听说 eval(repr(obj)) == obj 很好,但对于更复杂的对象却被抛弃了,调试的可读性是唯一的实际目标。 【参考方案1】:

__repr__ 方法旨在为开发人员而不是最终用户生成最有用的输出,因此只有您才能真正回答这个问题。但是,我通常会选择选项 B。选项 A 不是很有用,选项 C 是不必要的冗长——你不知道你的模块是如何导入的。其他人可能更喜欢选项 C。

但是,如果要存储 Python 对象是数据库,请使用pickle

import pickle
bob = InfoObj(Name="Bob")

> pickle.dumps(bob)
b'...some bytestring representation of Bob...'

> pickle.loads(pickle.dumps(bob))
Bob(...)

如果您使用的是较旧的 Python(3.x 之前的版本),请注意cPickle 更快,但pickle 更具可扩展性。 Pickle 无需任何配置即可在您的某些类上工作,但对于更复杂的对象,您可能需要编写自定义pickler。

【讨论】:

哇,这太容易了。 另外,设施是 Python 2.5.2。 泡菜是旧的。见docs.python.org/release/1.4/lib/… 既然我们已经在谈论pickle,你说自定义picklers...如果一个自定义类包含另一个自定义类的列表,那是其中一种情况吗?鉴于两者都不是很复杂,否则只是一些整数和字符串。 可能不会。我会使用自定义pickler来排除缓存的值,或者允许pickle包含对你不应该pickle的对象的引用的东西,比如sockets。

以上是关于对于自定义 Python 类,哪个 __repr__ 更好?的主要内容,如果未能解决你的问题,请参考以下文章

自定义 __repr__ 作为从 Enum 派生的类的类方法

Python进阶-----通过类的内置方法__str__和__repr__自定制输出(打印)对象时的字符串信息

为自己定义每个python类添加__repr__和__str__

Python详解类的 __repr__() 方法

Python中的__str__()方法和__repr__()方法

如何使用 SWIG 为 C++ 类提供 Python __repr__()