如何替换函数的__str__
我想把一个Python函数的字符串表示改成只有函数名。
比如说,有一个函数:
def blah(x):
...
str(blah)
现在返回的是:
<function blah at 0x10127b578>
所以我像这样替换了 __str__
:
blah.__str__=lambda: 'blah'
但是用 str(blah)
时并没有调用这个替换。
有没有办法改变函数的 __str__
?
4 个回答
3
如前所述,答案是否定的。如果你只是想把一个函数的名字变成字符串,可以用 blah.__name__
。
4
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
你可以创建一个简单的装饰器。
10
像这样替换 __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 内置的函数类型在某些方面确实是特别的(我说错了),其中之一就是你不能给它的属性赋值(这里指的是类本身的属性,而不是任何特定函数对象的属性)。所以在你想着如果能修改内置函数类型,让 str
在 所有 函数上都按你想要的方式工作,那是不可能的。这可能是件好事;修改像内置函数类型这样全球性的基本东西,很可能会引入一些奇怪的错误。
6
正如Joran所说:
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)