在python中将基类添加到现有对象

Her*_*nan 7 python inheritance monkeypatching metaclass

我有几个不同种类的对象(不同的函数名称,不同的签名),我对它们进行修补,以便有一种从不同函数访问它们的通用方法.简而言之,有一个调度程序可以获取我想要修补的对象,并根据它调用不同修补程序的对象类型.修补程序将向对象添加方法:

def patcher_of_some_type(object):

    def target(self, value):
        # do something and call self methods

    object.target = types.MethodType(target, object)

    # many more of these
Run Code Online (Sandbox Code Playgroud)

随着程序变得越来越复杂,围绕对象(或对象类)的包装似乎更好.一些修补程序共享公共代码或相互关联.但我不控制对象创建,也不控制类创建.我只得到了这些物品.即使我能做到这一点,我只想包装(或修补)某些对象,而不是所有对象.

一种解决方案可能是为现有对象添加基类,但我不确定这是多么可维护和安全.还有其他解决方案吗?

eca*_*mur 11

动态修改对象的类型是相当安全的,只要额外的基类是兼容的(如果不是,你会得到一个例外).添加基类的最简单方法是使用3参数type构造函数:

cls = object.__class__
object.__class__ = cls.__class__(cls.__name__ + "WithExtraBase", (cls, ExtraBase), {})
Run Code Online (Sandbox Code Playgroud)

  • 仅当您需要设置类名时才需要使用 type (并且请仅使用 `type` 而不是 `object.__class__.__class__`,顺便说一句,旧式类会失败!),否则您可以只执行 `class AnyNameHere (cls, ExtraBase): pass` 更具可读性。 (3认同)

Jac*_*ing 7

基于对另一个答案的评论,这是修补基类的另一种方法:

class Patched(instance.__class__, ExtraBase):
    pass

instance.__class__ = Patched
Run Code Online (Sandbox Code Playgroud)

  • 这真的很整洁!但它似乎确实将类名更改为Patched.你可以通过添加一行来解决这个问题:`Patched .__ name__ = instance .__ class __.__ name__`. (3认同)