(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"
没有运气。
答案 0 :(得分:8)
如果要控制如何显示类的实例,正确的方法是覆盖__format__
方法。通常,您可以覆盖的三种方法用于:
__repr__
- 当对象需要在交互式解释器中显示时使用,通常作为调试辅助工具。它应该是一个字符串,可以在评估时重新创建对象。__str__
- 当对象传递给str
时使用,或在print
尝试显示对象时调用。没有其他定义,它只需调用__repr__
。这是"默认"实例的字符串表示。__format__
- 当您的对象是str.format
的参数时使用。它在替换字段中的可选:
之后显示格式规范(如果有)作为附加参数。这是一个表示数字对的类的简单示例。用于分隔数字的字符可以通过格式规范进行配置。
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__
方法可以正常运行。
当我想将类的对象同时打印到终端和日志文件时,我已经使用了它。我只希望将它们完整地打印到日志文件中,并在终端上显示截断的版本,所以我写了类似的内容。
希望这会有所帮助。