使用集合类 Python 的 __repr__ 的最佳实践是什么?

我有一个自定义 Python 类,它本质上封装了list某种对象,我想知道我应该如何实现它的__repr__功能。我很想选择以下内容:


class MyCollection:

   def __init__(self, objects = []):

      self._objects = []

      self._objects.extend(objects)


   def __repr__(self):

      return f"MyCollection({self._objects})"

这具有生成完整描述类实例的有效 Python 输出的优点。然而,在我的真实情况下,对象列表可能相当大,每个对象本身可能有一个很大的 repr(它们本身就是数组)。


在这种情况下的最佳做法是什么?接受 repr 可能通常是一个很长的字符串?是否存在与此相关的潜在问题(调试器 UI 等)?我应该使用分号实施某种缩短方案吗?如果是这样,是否有一种好的/标准的方法来实现这一目标?或者我应该完全跳过列出集合的内容吗?


FFIVE
浏览 134回答 1
1回答

红糖糍粑

官方文档将此概述为您应该如何处理 __repr__:由 repr() 内置函数调用以计算对象的“官方”字符串表示形式。如果可能的话,这应该看起来像一个有效的 Python 表达式,可用于重新创建具有相同值的对象(给定适当的环境)。如果这不可能,则应返回 <...some useful description...> 形式的字符串。返回值必须是字符串对象。如果一个类定义了 __repr__() 而不是 __str__(),那么当需要该类实例的“非正式”字符串表示时,也会使用 __repr__()。这通常用于调试,因此表示信息丰富且明确非常重要。Python 3__repr__文档列表、字符串、集合、元组和字典都在它们的 __repr__ 方法中打印出它们的整个集合。您当前的代码看起来完全遵循文档建议的示例。尽管我建议更改您的 __init__ 方法,使其看起来更像这样:class MyCollection:&nbsp; &nbsp;def __init__(self, objects=None):&nbsp; &nbsp; &nbsp; &nbsp;if objects is None:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;objects = []&nbsp; &nbsp; &nbsp; self._objects = objects&nbsp; &nbsp;def __repr__(self):&nbsp; &nbsp; &nbsp; return f"MyCollection({self._objects})"您通常希望避免使用可变对象作为默认参数。从技术上讲,由于您的方法是使用 extend (它制作列表的副本)实现的,它仍然可以很好地工作,但是 Python 的文档仍然建议您避免这种情况。不使用可变对象作为默认值是一种很好的编程习惯。相反,使用 None 作为默认值并在函数内部检查参数是否为 None 并创建一个新的列表/字典/无论是否是。https://docs.python.org/3/faq/programming.html#why-are-default-values-shared-between-objects如果您对另一个库如何以不同方式处理它感兴趣,当数组长度大于 1,000 时,Numpy 数组的 repr 仅显示前三项和后三项。它还对项目进行格式化,以便它们都使用相同数量的空间(在下面的示例中,1000 占用四个空间,因此 0 必须用另外三个空间填充才能匹配)。>>> repr(np.array([i for i in range(1001)]))'array([&nbsp; &nbsp;0,&nbsp; &nbsp; 1,&nbsp; &nbsp; 2, ...,&nbsp; 998,&nbsp; 999, 1000])'要模仿这种 numpy 数组样式,您可以在您的类中实现这样的 __repr__ 方法:class MyCollection:&nbsp; &nbsp;def __init__(self, objects=None):&nbsp; &nbsp; &nbsp; if objects is None:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; objects = []&nbsp; &nbsp; &nbsp; self._objects = objects&nbsp; &nbsp;def __repr__(self):&nbsp; &nbsp; &nbsp; &nbsp;# If length is less than 1,000 return the full list.&nbsp; &nbsp; &nbsp; if len(self._objects) < 1000:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return f"MyCollection({self._objects})"&nbsp; &nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Get the first and last three items&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; items_to_display = self._objects[:3] + self._objects[-3:]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Find the which item has the longest repr&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; max_length_repr = max(items_to_display, key=lambda x: len(repr(x)))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Get the length of the item with the longest repr&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; padding = len(repr(max_length_repr))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Create a list of the reprs of each item and apply the padding&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; values = [repr(item).rjust(padding) for item in items_to_display]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Insert the '...' inbetween the 3rd and 4th item&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; values.insert(3, '...')&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Convert the list to a string joined by commas&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; array_as_string = ', '.join(values)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return f"MyCollection([{array_as_string}])">>> repr(MyCollection([1,2,3,4]))'MyCollection([1, 2, 3, 4])'>>> repr(MyCollection([i for i in range(1001)]))'MyCollection([&nbsp; &nbsp;0,&nbsp; &nbsp; 1,&nbsp; &nbsp; 2, ...,&nbsp; 998,&nbsp; 999, 1000])'
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python