Как изменить представление функции Python?
>>> def hehe():
... return "spam"
...
>>> repr(hehe)
'<function hehe at 0x7fe5624e29b0>'
Я хочу иметь:
>>> repr(hehe)
'hehe function created by awesome programmer'
Как мне это сделать? Включение функции __repr__
внутри hehe
не работает.
EDIT:
В случае, если вы, ребята, задаетесь вопросом, почему я хочу это сделать:
>>> defaultdict(hehe)
defaultdict(<function hehe at 0x7f0e0e252280>, {})
Мне просто не нравится, как это показано здесь.
Ответы
Ответ 1
Обычно, когда вы хотите что-то изменить в функции, скажем, подписи функции, поведения функции или атрибутов функции, вы должны рассмотреть возможность использования декоратора. Итак, вот как вы можете реализовать то, что хотите:
class change_repr(object):
def __init__(self, functor):
self.functor = functor
# lets copy some key attributes from the original function
self.__name__ = functor.__name__
self.__doc__ = functor.__doc__
def __call__(self, *args, **kwargs):
return self.functor(*args, **kwargs)
def __repr__(self):
return '<function %s created by ...>' % self.functor.__name__
@change_repr
def f():
return 'spam'
print f() # spam
print repr(f) # <function hehe created by ...>
Обратите внимание, что вы можете использовать только декоратор на основе класса, так как вам нужно переопределить __repr__
метод, который вы не можете сделать с объектом функции.
Ответ 2
Нет, вы не можете изменить представление объекта функции; если вы хотите добавить документацию, вы должны добавить docstring:
def foo():
"""Frob the bar baz"""
и получите доступ к help(foo)
или print foo.__doc__
.
Вы можете создать вызываемый объект с пользовательским __repr__
, который действует точно так же, как функция:
class MyCallable(object):
def __call__(self):
return "spam"
def __repr__(self):
return 'hehe function created by awesome programmer'
Демо:
>>> class MyCallable(object):
... def __call__(self):
... return "spam"
... def __repr__(self):
... return 'hehe function created by awesome programmer'
...
>>> hehe = MyCallable()
>>> hehe
hehe function created by awesome programmer
>>> hehe()
'spam'
Ответ 3
Непосредственно ответ на ваш вопрос, но, возможно, вам действительно нужна документация?
>>> def hehe():
... '''hehe function created by awesome programmer'''
... return 'spam'
...
>>> help(hehe)
Help on function hehe in module __main__:
hehe()
hehe function created by awesome programmer
Ответ 4
Вот немного более гибкая версия того, что у Александра Жукова answer:
def representation(repr_text):
class Decorator(object):
def __init__(self, functor):
self.functor = functor
def __call__(self, *args, **kwargs):
return self.functor(*args, **kwargs)
def __repr__(self):
return (repr_text % self.functor.__name__ if '%' in repr_text
else repr_text)
return Decorator
from collections import defaultdict
@representation('<function %s created by awesome programmer>')
def f():
return list
dd = defaultdict(f)
print repr(dd)
Вывод:
defaultdict(<function f created by awesome programmer>, {})
Так как representation()
возвращает декоратор, если вы хотите иметь один и тот же шаблон на нескольких функциях, вы можете сделать что-то вроде этого:
myrepr = representation('<function %s created by awesome programmer>')
@myrepr
def f():
...
@myrepr
def g():
...
etc