Как заменить str для функции
Я хочу изменить строковое представление функции python, чтобы быть только именем функции.
например, для некоторой функции
def blah(x):
...
str(blah)
В настоящее время дает
<function blah at 0x10127b578>
поэтому я заменяю __str__
такой:
blah.__str__=lambda: 'blah'
но он не вызывается str(blah)
.
можно ли изменить __str__
функции?
4 ответов
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)
замена __str__
как это не работает на любом типе объекта. Встроенный тип функции не является особенным:
>>> class Foo(object):
pass
>>> f = Foo()
>>> f.__str__ = lambda: 'f'
>>> str(f)
'<__main__.Foo object at 0x0000000002D13F28>'
>>> f.__str__()
'f'
на str
builtin не ищет __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 встроенный тип функции is специальный в некоторых отношениях (я солгал), один из которых заключается в том, что вы не можете назначить его атрибутам (это атрибуты класс, а не атрибуты какого-либо конкретного объекта функции). Поэтому, прежде чем вы думаете, может быть, было бы здорово, если бы вы могли monkeypatch встроенный тип функции, так что str
работала так вы хотите на все функции, это не работает. Вероятно, это к лучшему; изменение таких глобальных и фундаментальных вещей, как тип встроенной функции, было бы отличным способом изобрести некоторые действительно странные ошибки.
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
Как уже отмечалось, ответа нет. Если вы просто хотите, чтобы получить имя функции в виде строки, вы можете использовать blah.__name__
.