python - __repr__ 用于(大型)复合对象

标签 python biginteger representation

我希望为我的复合对象(即由其他(可能是复合的)对象组成的对象)提供信息表示。但是,因为我的代码从根本上处理高精度数字(请不要问我为什么不只使用 double ),所以我最终会得到如下所示的表示形式:http://pastebin.com/jpLgAfxC 。坚持使用默认值 __repr__ 会更好吗? ?

最佳答案

是否有详细的repr取决于您想要完成的任务。对于复杂或复合对象,我知道我更喜欢以下哪一个:

Point(x=1.12, y=2.2, z=-1.9)
<__main__.Point object at 0x103011890>

它们都告诉我对象是什么类型,但只有第一个清楚所涉及的所有(相关)值,并避免仅在极少数情况下相关的低级信息。

我喜欢看到真正的值(value)观。但是,鉴于您的值(value)观是如此巨大,您的情况是一个特例:

72401317106217603290426741268390656010621951704689382948334809645
87850348552960901165648762842931879347325584704068956434195098288
38279057775096090002410493665682226331178331461681861612403032369
73237863637784679012984303024949059416189689048527978878840119376
5152408961823197987224502419157858495179687559851

它们不能用于大多数开发或调试目的。我确信有时您需要完整的序列化 - 例如,发送到文件或从文件发送。但这些一定相当罕见,不是吗?我无法想象你真的记住了所有 309 个数字,或者可以通过目视判断上面的数字与下面的数字是否相同:

72401317106217603290426741268390656010621951704689382948334809645
87850348552960901165648762842931879347325584704068956434195098288
38279057775096090002410493665682226331178331461681861612403032369
73327863637784679012984303024949059416189689048527978878840119376
5152408961823197987224502419157858495179687559851

它们不一样。但除非你是斯波克或终结者,否则你不会一眼就知道这一点。 (实际上,我在这里让它变得更容易,长度包裹以避免水平滚动。)

所以我建议(大量)缩短它们的表示,以使输出更容易处理。这就像每次想要打印 Chapter 对象时打印出整个章节文本。矫枉过正。

相反,尝试一些更短、更容易使用的东西。截断和/或省略号是有用的。例如

72401...59851
7240131710... 

您也可以使用对象 ID。如果您的高精度类型是 HP,则:

HP(0x103011890)

至少这样你就能够区分它们了。然而,使用对象 id 的一个缺点是,对象在逻辑上可能是等效的,但如果您创建具有相同逻辑值的多个对象,它们将具有不同的 id,因此当它们不同时,它们会显得不同。您可以通过创建自己的短哈希函数来解决这个问题。散列有一点艺术性,但对于代表来说,即使是简单的东西也可以。例如:

import binascii, struct

def shorthash(s):
    """
    Given a Python value, produce a short alphanumeric hash that
    helps identify it for debugging purposes. A riff on 
    http://stackoverflow.com/a/2511059/240490
    Enhanced to remove trailing boilerplate, and to work
    on either Python 2 or Python 3.
    """
    hashbytes = binascii.b2a_base64(struct.pack('l', hash(s)))
    return hashbytes.decode('utf-8').rstrip().rstrip("=")

然后在高精度类别中定义您的代表:

def __repr__(self):
    clsname = self.__class__.__name__
    return '{0}({1}).format(clsname, shorthash(self.value))

其中 self.value 是创建数百位值的任何本地属性、属性或方法。如果您要子类化 int,则这可能只是 self

这可以让你:

HP(Tea+5MY0WwA)

上面两个巨大的、几乎相同的数字?使用此方案,它们呈现为:

HP(XhkG0358Fx4)
HP(27CdIG5elhQ)

这显然是不同的。您可以将其与一些值表示结合起来。例如。一些替代方案:

HP(~7.24013e308 @ XhkG0358Fx4)
HP(dig='72401...59851', ndigits=309, hash='XhkG0358Fx4')

您会发现这些较短的值在调试上下文中更有用。当然,您可以保留方法或属性(例如 .value.digits.alldigits),以应对以下情况:您需要每一点,但将常见情况定义为更容易消耗的东西。

关于python - __repr__ 用于(大型)复合对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29375477/

相关文章:

python - 生成 MIDI 文件并播放它而不将其保存到磁盘

c - 修改C中for循环的表示

python/matplotlib 绘图相当于 R 的符号图?

java - BigInteger 到 byte[]

java - 这段代码的哪一部分正在减慢我的程序

stack - 堆栈的写时复制

datetime - 代表一天的最佳格式是什么?

c - 用 C 查找下一个 IEEE 754 可表示数(朝向 -INF)?

python - 在没有安装 xlwings 的情况下分发 xlwings 宏?

python - Python 图中的高斯拟合