像这样替换 __str__ 永远不会真正适用于任何类型的对象。内置函数类型并不特殊:
>>> class Foo(object):
pass
>>> f = Foo()
>>> f.__str__ = lambda: 'f'
>>> str(f)
'<__main__.Foo object at 0x0000000002D13F28>'
>>> f.__str__()
'f'
str 内置函数不会通过通常的查找协议查找 __str__,它会直接跳到查看其参数的类。所以你不能在单个对象上“覆盖”__str__ 方法;您必须在一个类上设置它以应用于该类的所有对象。1
但话又说回来,内置函数类型并不特殊。您可以创建一个行为类似于函数的类,并使用它来代替:
class Function(object):
def __init__(self, raw_function):
self.raw_function = raw_function
def __call__(self, *args, **kwargs):
return self.raw_function(*args, **kwargs)
def __str__(self):
return self.raw_function.__name__
__call__ 方法意味着您可以像调用函数一样调用此类的对象。这个只是将它接收到的任何参数直接传递给底层原始函数并返回它返回的任何东西(或抛出它抛出的任何异常)。而且由于这个类将单个函数作为参数,它也适合装饰器的模式:
@Function
def blah(x):
return x + 1
这样:
>>> blah
<__main__.Function object at 0x0000000002D13EB8>
>>> str(blah)
'blah'
>>> blah(33)
34
1 内置函数类型 在某些方面是特殊的(我撒谎了),其中之一是您不能分配给它的属性(即class 本身,而不是任何特定函数对象的属性)。因此,在您认为如果您可以对内置函数类型进行monkeypatch 以便str 在所有 函数上以您希望的方式工作之前可能会很棒,但这是行不通的。这可能是最好的;像内置函数类型一样修改全局和基本的东西将是发明一些非常奇怪的错误的好方法。