【问题标题】:Possible to change a function's repr in python?可以在python中更改函数的repr吗?
【发布时间】:2017-12-14 21:09:22
【问题描述】:

我只看到了在类定义中设置__repr__ 方法的示例。是否可以在函数定义中或定义函数后更改__repr__

我尝试过没有成功...

>>> def f():
    pass
>>> f
<function f at 0x1026730c8>
>>> f.__repr__ = lambda: '<New repr>'
>>> f
<function __main__.f>

【问题讨论】:

  • 虽然装饰器很有趣,但似乎更简单的答案是首先不创建函数,而是直接使用 __repr____call__ 方法创建一个类,然后可以调用就好像它是一个函数一样。

标签: python function repr


【解决方案1】:

不,因为repr(f) 改为type(f).__repr__(f)

【讨论】:

    【解决方案2】:

    是的,如果你愿意放弃实际上是一个函数的函数。

    首先,为我们的新类型定义一个类:

    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 装饰器,也会发生更新。
    【解决方案3】:

    为此,您需要更改给定类的 __repr__ 函数,在本例中为内置函数类 (types.FunctionType)。因为在 Python 中你不能编辑内置类,只能对它们进行子类化,你不能。

    但是,您可以采用两种方法:

    1. 按照 kwatford 的建议包装一些函数
    2. 使用您自己的 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__()

    【讨论】:

      猜你喜欢
      • 2014-08-02
      • 2014-04-24
      • 2022-07-06
      • 1970-01-01
      • 1970-01-01
      • 2022-09-28
      • 1970-01-01
      相关资源
      最近更新 更多