如何将__repr__与多个参数一起使用?

时间:2016-11-15 00:44:16

标签: python python-3.x

(Python 3.5.2)

我为我的一个课程定义了__repr__,如下所示:

class d():
    def __init__(self):
        self._values = []
        return
    def __pos__(self):
        return self._values[0]
    def __repr__(self, value):
        self._values.append(value)
        return

现在我想要

x = d()
print(x,"a")
print(+x)

返回

a

但我得到了

TypeError: __repr__() missing 1 required positional argument: 'value'

我尝试了一些变种,例如print(x),"a"没有运气。

3 个答案:

答案 0 :(得分:8)

如果要控制如何显示类的实例,正确的方法是覆盖__format__方法。通常,您可以覆盖的三种方法用于:

  1. __repr__ - 当对象需要在交互式解释器中显示时使用,通常作为调试辅助工具。它应该是一个字符串,可以在评估时重新创建对象。
  2. __str__ - 当对象传递给str时使用,或在print尝试显示对象时调用。没有其他定义,它只需调用__repr__。这是"默认"实例的字符串表示。
  3. __format__ - 当您的对象是str.format的参数时使用。它在替换字段中的可选:之后显示格式规范(如果有)作为附加参数。
  4. 这是一个表示数字对的类的简单示例。用于分隔数字的字符可以通过格式规范进行配置。

    class Pair():
        def __init__(self, x, y):
            self.x = x
            self.y = y
    
        def __format__(self, spec):
            return "{}{}{}".format(self.x, spec, self.y)
    
        def __str__(self):
            return "{:/}".format(self)
    
        def __repr__(self):
            return "Pair({}, {})".format(self.x, self.y) 
    

    可以按如下方式使用:

    >>> x = Pair(1,2)
    >>> x  # using __repr__
    Pair(1, 2)
    >>> str(x)   # using __str__, with a default separator of /
    '1/2'
    >>> print(x)  # uses __str__ implicitly
    1/2
    >>> "{}".format(x)  # no separator specified
    '12'
    >>> "{:-}".format(x)  # use - to separate the two numbers
    '1-2'
    

答案 1 :(得分:2)

您以错误的方式使用__repr____repr__应该用于以可打印的格式化方式返回对象的表示形式。与Python相反,只需打印对象的名称和内存地址。根据{{​​1}}的文档:

  

__repr__内置函数调用以计算对象的“官方”字符串表示形式。如果可能的话,这应该看起来像一个有效的Python表达式,可用于重新创建具有相同值的对象(给定适当的环境)。如果这不可能,则形式为< ...一些有用的描述的字符串...>应该退还。返回值必须是字符串对象。如果一个类定义repr()但不定义__repr__(),那么当需要该类的实例的“非正式”字符串表示时,也会使用__str__()

我真的不确定你尝试使用__repr__()做什么。如果您只是想通过__repr__的方法向self.values添加元素,请抛弃魔术方法并创建自己的方法:

d

答案 2 :(得分:1)

有人说您永远不要在__str____repr__上添加参数,但我不同意。

例如,如果要显示类对象的字符串表示形式,则可以编写自定义__str__。但是,如果某些对象真的很长怎么办?有时您可能想要截断那些对象,有时您可能需要完整的对象。

class Compute:

    def __init__(self, foo, ...):
        self.foo = foo
        ...

    def __str__(self, trunc=False):
        return_str = ''
        for item in self.__dict__:
            if trunc:
                # If the length of the str representation of the item is long, shorten it.
                return_str += f'\n{item} = {self.__dict__[item] if len(str(self.__dict__[item] < 50) else str(self.__dict__[item])[:51]}'
            else:
                # This would be whatever your usual __str__ method returns
                return_str += f'\n{item} = {self.__dict__[item]}'

        return return_str

您可以使用以下命令简单地调用它:

bar = Compute(foo=...)

print(bar.__str__(trunc=True))

现在,如果您的__init__包含任何对象,这些对象的字符串长度特别长(例如,您有大量的数据列表),它将仅显示第51个字符。

您还可以为希望打印截断的字符串添加更多逻辑。

我建议在dunder方法中将默认参数设置为False。这意味着除非明确要求,否则__str__方法可以正常运行。

当我想将类的对象同时打印到终端和日志文件时,我已经使用了它。我只希望将它们完整地打印到日志文件中,并在终端上显示截断的版本,所以我写了类似的内容。

希望这会有所帮助。