repr

时间:2018-06-14 19:20:22

标签: python repr

所以我有这个类实现了repr方法

import reprlib

class Test:
    def __init__(self, aList):
        self.my_list = [c for c in aList]

    def __repr__(self):
#         return " ".join((str(i) for i in self.my_list))
#         return reprlib.repr(self.my_list)
#         return repr(self.my_list)  # builtin repr method
        return str(self.my_list)

repr方法的各种实现之间有什么区别?

它们都具有相同的输出。

所有实施中使用的代码:

x = [2, 5, 11]
t = Test(x)
print(t)  # >> [2, 5, 11]
t  # >> output [2, 5, 11]

编辑: 第一个实现(join方法)将生成没有括号的项目。 如果你愿意,请不要理会。我的重点是最后三个之间的差异,这是所有四个实施中更好的实施。

编辑: 这显然不是关于repr和str方法之间的差异。 关于在实现repr方法(或者str方法)时我应该始终采用哪种实现方式。

3 个答案:

答案 0 :(得分:1)

首先,会写什么:

def __repr__(self):
    return '%s(%r)' % (self.__class__.__qualname__, self.my_list)

这保留了repr的主要目的:告诉类和值的重要部分。您可以将__qualname__替换为__name__,或添加__module__,但我发现这是最佳平衡。

有时,对于更复杂的情况(大多数情况下,每当repr的某些部分只能有条件地出现时),我写了类似的东西:

def __repr__(self):
    bits = []
    bits.append(...)
    return ''.join(bits)

你的所有答案都缺少课程,所以我不会在下面再提一下。

def __repr__(self):
    return " ".join((str(i) for i in self.my_list))

由于很多原因,这很糟糕,虽然可以修复:

  • 缺少括号。要解决此问题,请使用'[%s]' % ...
  • 缺少逗号。要解决此问题,请使用', '.join(...)
  • 毫无意义地使用生成器理解。与列表推导相比,生成器非常慢,因此每当您立即使用整个值时,始终使用列表推导。
  • 致电str而非repr。这会为['1', '2', '3']
  • 之类的内容产生令人困惑的输出
def __repr__(self):
    return reprlib.repr(self.my_list)

这将在一些元素之后截断列表。老实说,我发现这比其他任何东西都更烦人。

我从该模块中使用的唯一函数是reprlib.recursive_repr装饰器,即使只是在极少数情况下我不能只调用已经递归感知的builtin repr。值得注意的是,list是,所以你在这里不需要它。

def __repr__(self):
    return repr(self.my_list)

这与你的任何答案一样正确。可能会导致特别长的列表出现问题。但是,由于代表需要的信息比此更多,因此最终值得使用'%r' % ...{!r}.format(...)

def __repr__(self):
    return str(self.my_list)

这恰好为list产生相同的输出,但在语义上是不正确的。

顺便说一下,而不是:

self.my_list = [c for c in aList]

使用:

self.my_list = list(aList)

答案 1 :(得分:1)

我未知的__repr__是最好的可能性,它应该允许复制实例(甚至可能使用eval()),而第二最好的是提供有关如何执行此操作的准确信息。

我对成熟__repr__的偏好是:

class Spammer:
    def __init__(self, members, hidden=False):
        self._list = list(members)
        self._hidden = hidden

    def __repr__(self):
        return 'Spammer(members={}, hidden={})'.format(self._list, self._hidden)

assert repr(Spammer([1,2], True)) == 'Spammer(members=[1, 2], hidden=True)'

这种方法的缺点是每次都必须更改__repr__ 您将更改引入__init__。此外__repr__也有失败的倾向 在IDE中没有任何例外,因此有必要进行明确的测试。

答案 2 :(得分:0)

这取决于你打算如何使用班级的报告。

  • 如果您打算进行自定义格式化,或my_list属性可以是任何可迭代的(尽管记得避免丢失数据到repr)而不仅仅是列表,您应该做类似的事情str.join方法。

  • 如果您想考虑大小和修剪(使大型列表显示为Test([x, y, z, ...])或其他内容),请考虑使用reprlib,因为它具有相应的功能。

  • 如果您没有任何具体要求,请坚持最简单的方法(即reprstr,有时str.join