可以在python中更改函数的repr吗?
Posted
技术标签:
【中文标题】可以在python中更改函数的repr吗?【英文标题】:Possible to change a function's repr in python? 【发布时间】:2012-06-08 04:19:22 【问题描述】:我只看到了在类定义中设置__repr__
方法的示例。是否可以在函数定义中或定义后更改函数的__repr__
?
我尝试过没有成功...
>>> def f():
pass
>>> f
<function f at 0x1026730c8>
>>> f.__repr__ = lambda: '<New repr>'
>>> f
<function __main__.f>
【问题讨论】:
虽然装饰器很有趣,但似乎更简单的答案是首先不创建函数,而是直接使用__repr__
和 __call__
方法创建一个类,然后可以调用就好像它是一个函数一样。
【参考方案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
现在我们可以定义 repr 和函数:
@withrepr(lambda x: "<Func: %s>" % x.__name__)
def mul42(y):
return y*42
现在repr(mul42)
产生'<Func: mul42>'
【讨论】:
装饰器请使用functools.wraps
更新装饰函数的名称和文档字符串。
问题是print mul42.__name__
会引发函数不期望的 AttributeError。所以它会是:return wraps(func)(reprwrapper(reprfun, func))
来解决这个问题。
@ms4py 在这种情况下,我认为update_wrapper
稍微更合适/更直接。我已经修改了包装类,以便它在其构造函数中执行此操作。这样,即使您直接使用类而不是使用 withrepr
装饰器,也会发生更新。【参考方案2】:
不,因为repr(f)
改为type(f).__repr__(f)
。
【讨论】:
【参考方案3】:为此,您需要更改给定类的 __repr__
函数,在本例中为内置函数类 (types.FunctionType
)。因为在 Python 中你不能编辑内置类,只能对它们进行子类化,你不能。
但是,您可以采用两种方法:
-
按照 kwatford 的建议包装一些函数
使用您自己的 repr 函数创建您自己的表示协议。例如,您可以定义一个 myrepr
函数,它首先查找 __myrepr__
方法,您不能将其添加到函数类,但您可以按照您的建议将其添加到单个函数对象(以及您的自定义类和对象) , 如果找不到 __myrepr__
,则默认为 repr。一个可能的实现是:
def myrepr(x):
try:
x.__myrepr__
except AttributeError:
return repr(x)
else:
return x.__myrepr__()
然后您可以定义__myrepr__
方法并使用myrepr
函数。或者,您也可以使用__builtins__.repr = myrepr
将您的函数设为默认repr
并继续使用repr
。尽管编辑 __builtins__
可能并不总是理想的,但这种方法最终会完全按照您的意愿行事。
【讨论】:
自定义 repr 协议很有趣,但它有点复杂,因为您还需要考虑列表、字典或类似内容中的嵌套对象。【参考方案4】:这似乎很难。 Kwatford 的方法仅部分解决了这个问题,因为它不适用于类中的函数,因为self
将被视为位置参数,如Decorating Python class methods - how do I pass the instance to the decorator? 中所述 - 但是,该问题的解决方案不适用于这种情况,不幸的是,使用__get__()
和functools.partial
会覆盖自定义__repr__()
。
【讨论】:
以上是关于可以在python中更改函数的repr吗?的主要内容,如果未能解决你的问题,请参考以下文章