可以在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) 产生'&lt;Func: mul42&gt;'

【讨论】:

装饰器请使用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吗?的主要内容,如果未能解决你的问题,请参考以下文章

Python中的repr()函数

python-repr()和val()函数

理解 Python 中的 repr() 函数

如何为函数本身设置 repr? [复制]

Python中str()和repr()函数的区别

Matlab repr 函数