有什么方法可以将 **kwargs 添加到 __str__() 的对象签名中?

Any way to add **kwargs to __str__()'s signature of an object?

我希望能够更改 __str__() 的输出,并希望为此添加 **kwargs

问题:似乎无法更改函数的签名。

例如:

#!/usr/bin/env python3

class my_printable_obj(object):

    def __init__(self, s):
        self.content = s

    def __str__(self, **kwargs):
        fancy = kwargs.get('fancy', '')
        return str(self.content) + fancy



M = my_printable_obj("Something to print")

print(str(M))
print(str(M, fancy=' + a fancy part'))

输出:

$ ./test_script3str.py 
Something to print
Traceback (most recent call last):
  File "./test_script3str.py", line 17, in <module>
    print(str(M, fancy=' + a fancy part'))
TypeError: 'fancy' is an invalid keyword argument for this function

我注意到,尽管有 TypeError 消息,python 确实使用了 my_printable_obj.__str__()(在 __str__() 的开头添加一个 print('here') 让我们很容易观察到这一点)。

是否有解决方案,或者由于某种原因无法解决?然后我应该更好地定义另一个函数,比如 into_str(self, **kwargs) 并使用 M.into_str(fancy=' something more') 而不是 __str__()?

注意:写这个:

def __str__(self, fancy=''):
    return str(self.content) + fancy

给出完全相同的错误。

您使用 kwarg 调用的函数是 str (the inbuilt function)

str() 确实在您的对象上调用了 __str__ 方法。


也许您正在寻找的是__format__

>>> class MyPrintableObj(object):

    def __init__(self, s):
        self.content = s

    def __format__(self, formatstr):
        return str(self.content) + formatstr

>>> m = MyPrintableObj("Something to print")
>>> '{: a fancy string}'.format(m)
'Something to print a fancy string'

内置的str是一个type。当你执行类似 str(custom_object) 的东西时,str 的构造函数调用对象的 __str__() 方法。您不能在不覆盖的情况下更改类型的签名(这不是一个好主意)。

class _str(str):
    def __new__(cls, *args, **kwargs):
        if args:
            obj = args[0]
            if hasattr(obj, '__str__'):
                return obj.__str__(**kwargs)
        return str.__new__(cls, *args, **kwargs)
str = _str

是的,这显然不是个好主意,但这是用法:

class Example:
    def __str__(self, **kwargs):
        return 'kwargs: {}'.format(kwargs)

print str(Example(), arg1=1, arg2=2)
# kwargs: {'arg1': 1, 'arg2': 2}

尽管它是一个 "dunder" 方法,但在您的自定义对象上显式调用 __str__ 方法可能是一个更好的主意。