9

__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(),至少除非我想出更好的方法。队友手动创建完整对象而不是通过适当的接口函数的结果只是一种类型的信息检索可能不稳定,直到有人弄清楚他做了什么。

4

1 回答 1

13

__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。

于 2011-06-15T02:52:36.450 回答