__repr__用于(大)复合对象

时间:2015-03-31 18:09:04

标签: python biginteger representation

我想为我的复合对象(即由其他(可能是复合的)对象组成的对象)提供信息表示。但是,因为我的代码从根本上处理高精度数字(请不要问我为什么我不只是使用双打),我最终会得到你在这里看到的陈述:http://pastebin.com/jpLgAfxC。坚持使用默认的__repr__

会更好吗?

2 个答案:

答案 0 :(得分:2)

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

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

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

我喜欢看到真正的价值观。但是,你的是一个特例,因为你的价值观非常可怕:

72401317106217603290426741268390656010621951704689382948334809645
87850348552960901165648762842931879347325584704068956434195098288
38279057775096090002410493665682226331178331461681861612403032369
73237863637784679012984303024949059416189689048527978878840119376
5152408961823197987224502419157858495179687559851

它们对大多数开发或调试目的无用。我确定您有时需要完整的序列化 - 例如,发送到文件和从文件发送。但那些必须相当罕见,不是吗?我无法想象你真的记得所有309个数字,或者可以确定以上数字是否与目视检查中的数字相同:

72401317106217603290426741268390656010621951704689382948334809645
87850348552960901165648762842931879347325584704068956434195098288
38279057775096090002410493665682226331178331461681861612403032369
73327863637784679012984303024949059416189689048527978878840119376
5152408961823197987224502419157858495179687559851

他们不一样。但是,除非你是Spock或The Terminator,否则你不会从中快速了解这一点。 (实际上,我在这里做得更容易,长度包装以避免必须水平滚动。)

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

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

72401...59851
7240131710... 

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

HP(0x103011890)

至少你可以将它们区分开来。然而,使用对象id的一个丑处是对象在逻辑上是等价的,但是如果你创建具有相同逻辑值的多个对象,它们会有不同的id,因此当它们不相同时会显得不同。您可以通过创建自己的短哈希函数来解决这个问题。哈希有一点艺术,但对于个人来说,即使是简单的东西也会起作用。 E.g:

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("=")

然后在高精度类中定义你的repr:

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),以满足您需要最后一点的情况,但将常见情况定义为更容易消费的东西。

答案 1 :(得分:0)

感谢Demian指向https://docs.python.org/2/reference/datamodel.html#object.repr的指针,具体为:

  

这通常用于调试,所以重要的是   表示是信息丰富和明确的。

在这种情况下,

http://pastebin.com/jpLgAfxC可能是最好的__repr__

相关问题