如何替换函数的__str__

mac*_*uff 6 python string function

我想将python函数的字符串表示更改为函数名称.

例如,某些功能

def blah(x):
 ...
Run Code Online (Sandbox Code Playgroud)

str(blah) 目前给出

<function blah at 0x10127b578>
Run Code Online (Sandbox Code Playgroud)

所以我这样替换__str__:

blah.__str__=lambda: 'blah'
Run Code Online (Sandbox Code Playgroud)

但它不会被调用str(blah).

是否可以更改__str__功能?

Ben*_*Ben 6

__str__像这样的替换永远不会对任何类型的对象起作用.内置函数类型并不特殊:

>>> class Foo(object):
    pass

>>> f = Foo()
>>> f.__str__ = lambda: 'f'
>>> str(f)
'<__main__.Foo object at 0x0000000002D13F28>'
>>> f.__str__()
'f'    
Run Code Online (Sandbox Code Playgroud)

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__
Run Code Online (Sandbox Code Playgroud)

__call__方法意味着您可以像调用函数一样调用此类的对象.这个只是将它直接接收的任何参数传递给底层的原始函数,并返回它返回的任何内容(或抛出它抛出的任何异常).由于这个类只需要一个函数作为参数,它也适合装饰器的模式:

@Function
def blah(x):
    return x + 1
Run Code Online (Sandbox Code Playgroud)

接着就,随即:

>>> blah
<__main__.Function object at 0x0000000002D13EB8>
>>> str(blah)
'blah'
>>> blah(33)
34
Run Code Online (Sandbox Code Playgroud)

1内置函数类型在某些方面特殊的(我撒谎),其中一个是你不能赋予它的属性(这是本身的属性,而不是任何特定函数对象的属性).因此,在您认为可能会很好的情况下,如果您可以将内置函数类型monkeypatch以便str按照您想要的方式在所有函数上运行,那就不行了.它可能是最好的; 将内容修改为全局和基本内容,因为内置函数类型将是发明一些非常奇怪的错误的好方法.


Hyp*_*eus 5

正如乔兰所说:

class NamedFunction:
    def __init__(self, name, f):
        self.f = f
        self.name = name

    def __call__(self, *args, **kwargs):
        return self.f(*args, **kwargs)

    def __str__(self):
        return self.name


f = NamedFunction("lambda: 'blah'", lambda: 'blah')
print(f())
print(f)
Run Code Online (Sandbox Code Playgroud)