__repr__ 用于(大型)复合对象
__repr__ for (large) composite objects
我想为我的复合对象(即由其他(可能是复合的)对象组成的对象)提供信息表示。但是,因为我的代码从根本上处理高精度数字(请不要问我为什么不只使用双精度数),所以我最终得到的表示形式就像您在这里看到的:http://pastebin.com/jpLgAfxC。坚持使用默认值 __repr__
会更好吗?
感谢 Demian 对 https://docs.python.org/2/reference/datamodel.html#object.repr 的指点,特别是:
This is typically used for debugging, so it is important that the
representation is information-rich and unambiguous.
在这种情况下,http://pastebin.com/jpLgAfxC 可能是最好的 __repr__
。
是否冗长 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 或终结者,否则你不会一眼就知道这一点。 (实际上,我在这里使它变得更容易,长度环绕以避免必须水平滚动。)
所以我建议(大量)缩短它们的表示,使输出更易于处理。这就像每次要打印 Chapter
对象时都打印出整个章节文本。矫枉过正。
相反,请尝试更短且更易于使用的内容。截断 and/or 省略号很有用。例如
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
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 class:
def __repr__(self):
clsname = self.__class__.__name__
return '{0}({1}).format(clsname, shorthash(self.value))
其中 self.value
是任何本地属性,属性 或方法创建了多位值。如果你是 classing int
,这可能只是 self
.
这会让你:
HP(Tea+5MY0WwA)
上面两个巨大的、几乎相同的数字?使用此方案,它们呈现为:
HP(XhkG0358Fx4)
HP(27CdIG5elhQ)
明显不同。您可以将它与一些值表示结合起来。例如。几个备选方案:
HP(~7.24013e308 @ XhkG0358Fx4)
HP(dig='72401...59851', ndigits=309, hash='XhkG0358Fx4')
您会发现这些较短的值在调试上下文中更有用。当然,您可以保留一个方法或 属性(例如 .value
、.digits
或 .alldigits
)用于那些您需要最后一点的情况,但是定义常见的情况是更容易消费。
我想为我的复合对象(即由其他(可能是复合的)对象组成的对象)提供信息表示。但是,因为我的代码从根本上处理高精度数字(请不要问我为什么不只使用双精度数),所以我最终得到的表示形式就像您在这里看到的:http://pastebin.com/jpLgAfxC。坚持使用默认值 __repr__
会更好吗?
感谢 Demian 对 https://docs.python.org/2/reference/datamodel.html#object.repr 的指点,特别是:
在这种情况下,This is typically used for debugging, so it is important that the representation is information-rich and unambiguous.
http://pastebin.com/jpLgAfxC 可能是最好的 __repr__
。
是否冗长 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 或终结者,否则你不会一眼就知道这一点。 (实际上,我在这里使它变得更容易,长度环绕以避免必须水平滚动。)
所以我建议(大量)缩短它们的表示,使输出更易于处理。这就像每次要打印 Chapter
对象时都打印出整个章节文本。矫枉过正。
相反,请尝试更短且更易于使用的内容。截断 and/or 省略号很有用。例如
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
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 class:
def __repr__(self):
clsname = self.__class__.__name__
return '{0}({1}).format(clsname, shorthash(self.value))
其中 self.value
是任何本地属性,属性 或方法创建了多位值。如果你是 classing int
,这可能只是 self
.
这会让你:
HP(Tea+5MY0WwA)
上面两个巨大的、几乎相同的数字?使用此方案,它们呈现为:
HP(XhkG0358Fx4)
HP(27CdIG5elhQ)
明显不同。您可以将它与一些值表示结合起来。例如。几个备选方案:
HP(~7.24013e308 @ XhkG0358Fx4)
HP(dig='72401...59851', ndigits=309, hash='XhkG0358Fx4')
您会发现这些较短的值在调试上下文中更有用。当然,您可以保留一个方法或 属性(例如 .value
、.digits
或 .alldigits
)用于那些您需要最后一点的情况,但是定义常见的情况是更容易消费。