如何为函数替换 __str__

Posted

技术标签:

【中文标题】如何为函数替换 __str__【英文标题】:How to replace __str__ for a function 【发布时间】:2014-05-12 22:01:06 【问题描述】:

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

例如某些功能

def blah(x):
 ...

str(blah) 目前给了

<function blah at 0x10127b578>

所以我像这样替换__str__

blah.__str__=lambda: 'blah'

但它没有被str(blah) 调用。

是否可以为函数更改__str__

【问题讨论】:

使用类代替... ***.com/questions/10493025/… 的可能重复项,因为您试图覆盖 function 类的 .__str__ 参数的实例,后者仅设计用于在类定义中替换。跨度> 只是一个小问题,一般来说我会避免这种事情,因为它会让其他可能不得不处理你的代码的人变得困难。虽然它很好且方便,但通常显式优于隐式 【参考方案1】:

正如乔兰所说:

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)

【讨论】:

啊,我正在提出一个几乎相同的答案...(+1 都一样:P)【参考方案2】:
class FNMagic:
     def __init__(self,fn,fn_name):
         self.fn = fn 
         self.fn_name = fn_name
     def __call__(self,*args,**kwargs):
         return self.fn(*args,**kwargs)
     def __str__(self):
         return self.fn_name


def blah(x):
    return x

blah = FNMagic(blah,"blah!")
print blah

你可以做一个简单的装饰器

class NamedFn:
    def __init__(self,name):
       self.fn_name = name
    def __call__(self,fn):
        return FNMagic(fn,self.fn_name)

@NamedFn("some_name!!!")
def blah2(x,y):
     return x*y

print blah2

【讨论】:

我对装饰器的经验有点了解,但这似乎是一个很好的用途。也许添加一些关于它的代码? 有一个简单的装饰器......(粗略的 FnMagic 类可以在装饰器中声明,但可以正常工作)【参考方案3】:

如前所述,答案是否定的。如果只想获取函数名作为字符串,可以使用blah.__name__

【讨论】:

【参考方案4】:

像这样替换 __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所有 函数上以您希望的方式工作之前可能会很棒,但这是行不通的。这可能是最好的;像内置函数类型一样修改全局和基本的东西将是发明一些非常奇怪的错误的好方法。

【讨论】:

以上是关于如何为函数替换 __str__的主要内容,如果未能解决你的问题,请参考以下文章

笔记如何为被装饰的函数保存元数据

ffmpeg - 如何为 h264_nvenc 编码器配置参考参数

如何为所有函数和类包含cpp文件但忽略main函数?

如何替换标题的所有字符

如何为所有列设置 AND 条件 - php

如何为django模型显示多个图像