【问题标题】:How to overwrite __repr__ method for an already-instantiated class python如何覆盖已经实例化的类 python 的 __repr__ 方法
【发布时间】:2019-09-18 23:45:29
【问题描述】:

我正在使用一个第 3 方库,它的类的 repr 很差,我想在创建该类的实例后覆盖它。

我看到了如何在现有对象中创建绑定方法。

class toy():
    pass

inst= toy()

class inhtoy():
    def __new__(cls,obj):
        def __repr__(self):
            return 'Sucessful'
        import types
        obj.__repr__ = types.MethodType(__repr__,obj)
        return obj

t = inhtoy(inst)

确实,如果我调用 t.repr(),它可以工作,但它不会覆盖原来的 repr。它显示为<bound method inhtoy.__new__.<locals>.__repr__ of <__main__.toy object at 0x7f76e0b61f98>> 一种局部方法。
调用 repr(t) 仍然指向原始表示 '<__main__.toy object at 0x7f76e0b61f98>' 但不是被覆盖的表示。

有没有办法正确地做到这一点?
谢谢

【问题讨论】:

  • 尽管他们的 __repr__ 可能很糟糕,但用您自己的替代品替换它会更加混乱。
  • 虽然我也想知道如何对实时实例执行此操作,但为什么不子类化他们的类并只更改__repr__
  • @Nullman 因为子类化需要用户继承它。它还会更改类名,生成与第 3 方库不兼容的问题。修改对象保持一切不变。

标签: python attributes new-operator overwrite


【解决方案1】:

使用子类并将其分配给实例,您可以像这样从库中获得该实例:

class Toy():
    pass
inst = Toy()  # from 3rd party library

class Toy_MyRepr(Toy):
    def __repr__(self):
        return '<my repr of Toy instance >'

inst.__class__ = Toy_MyRepr

【讨论】:

    【解决方案2】:

    @Nullman 的回答有效,因为他们的解决方案实际上是更改类对象 toyt 是一个实例,而不是实例本身,就像您的方法一样。

    特殊属性__class__ 引用实例所属的类对象。

    print(t.__class__ is toy) # True
    

    因此,t.__class__.__repr__ = my_custom_repr 分配给 __repr__toy,而不是实例 t

    在您的方法与 Nullman 的方法之间比较 print(t.__repr__) 的输出时,这一点变得可见。假设模块级函数__repr__ 如下所示:

    def __repr__(self):
        return repr(self.__class__)
    

    您的解决方案显示:

    <bound method __repr__ of <__main__.toy object at 0x00000000029E5A90>>
    

    注意,上面写着__main__.toy object
    Nullman 的解决方案显示为:

    <bound method __repr__ of <class '__main__.toy'>>
    

    当您使用您的方法调用t.__repr__() 时,您会调用您在实例t 上设置的方法,因此它会返回您让它返回的内容;您示例中的字符串 Success
    但是,当使用 repr() 时,定义了输出:

    类可以通过以下方式控制此函数为其实例返回的内容 定义一个__repr__() 方法。

    正如 Nullman 正确指出的那样,他们的方法将改变所有现有未来对象的行为,从 toy 实例化。


    至于奇怪的名字,使用你的代码时分配的方法显示:

    <bound method inhtoy.__new__.<locals>.__repr__ of <__main__.toy object at 0x7f76e0b61f98>>
    

    ...这是来自__qualname__ 特殊属性的函数对象的qualified name。它是你的类 inhtoy 的方法 __new__ 的本地范围内的函数 __repr__
    说到这一点,通过 inhtoy 类的魔术方法 __new__ 传递您的实例 inst 并没有真正实现太多。您的代码在功能上等同于:

    def __repr__(self):
        return "Success"
    
    inst.__repr__ = types.MethodType(__repr__, obj)
    

    【讨论】:

      【解决方案3】:

      您可以使用继承创建一个从感兴趣的类派生的新类,然后覆盖 repr 方法

      class inhtoy(toy):
      
          def __init__(self):
              toy.__init__(self)
      
          def __repr__(self):
              # Your repr method
      

      【讨论】:

        【解决方案4】:

        环顾四周后,我找到了this 的答案。在实时实例上执行此操作的方法是:

        t.__class__.__repr__ = my_custom_repr
        

        请注意,这会改变所有类实例,而不仅仅是这个实例

        【讨论】:

        • 好吧,就我的目的而言,它会起作用。您对它为什么会这样运作有任何见解吗?
        • 很遗憾没有,但如果你知道了,如果你让我知道,我会很高兴
        • @Nullman 我添加了一个答案,试图解释为什么您的解决方案有效而 OP 无效;如果您仍然感兴趣...
        猜你喜欢
        • 2023-02-09
        • 2021-12-10
        • 1970-01-01
        • 1970-01-01
        • 2012-07-19
        • 2011-04-21
        • 2022-09-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多