Можно изменить функцию rep в python?
Я видел примеры для установки метода __repr__
в определениях классов. Можно ли изменить функции __repr__
для функций либо в их определениях, либо после их определения?
Я попытался без успеха...
>>> def f():
pass
>>> f
<function f at 0x1026730c8>
>>> f.__repr__ = lambda: '<New repr>'
>>> f
<function __main__.f>
Ответы
Ответ 1
Да, если вы хотите отказаться от функции, фактически являющейся функцией.
Сначала определите класс для нового типа:
import functools
class reprwrapper(object):
def __init__(self, repr, func):
self._repr = repr
self._func = func
functools.update_wrapper(self, func)
def __call__(self, *args, **kw):
return self._func(*args, **kw)
def __repr__(self):
return self._repr(self._func)
Добавить в функцию декоратора:
def withrepr(reprfun):
def _wrap(func):
return reprwrapper(reprfun, func)
return _wrap
И теперь мы можем определить репер вместе с функцией:
@withrepr(lambda x: "<Func: %s>" % x.__name__)
def mul42(y):
return y*42
Теперь repr(mul42)
создает '<Func: mul42>'
Ответ 2
Нет, потому что repr(f)
выполняется как type(f).__repr__(f)
.
Ответ 3
Для этого вам нужно будет изменить функцию __repr__
для данного класса, которая в этом случае является встроенным классом функций (types.FunctionType
). Поскольку в Python вы не можете редактировать встроенные классы, только подклассировать их, вы не можете.
Однако есть два подхода, которым вы могли бы следовать:
- Оберните некоторые функции, предложенные Кватфордом
-
Создайте свой собственный протокол представления со своей собственной функцией репликации. Например, вы можете определить функцию myrepr
, которая сначала ищет методы __myrepr__
, которую вы не можете добавить в класс функций, но вы можете добавить ее к отдельным объектам функции, как вы предлагаете (а также к вашим пользовательским классам и объектам), тогда по умолчанию будет указано, если __myrepr__
не найден. Возможная реализация для этого:
def myrepr(x):
try:
x.__myrepr__
except AttributeError:
return repr(x)
else:
return x.__myrepr__()
Затем вы можете определить методы __myrepr__
и использовать функцию myrepr
. В качестве альтернативы вы также можете сделать __builtins__.repr = myrepr
, чтобы сделать вашу функцию по умолчанию repr
и продолжать использовать repr
. Этот подход в конечном итоге сделает именно то, что вы хотите, хотя редактирование __builtins__
может не всегда быть желательным.