我有不同种类的多个对象(不同的函数名,不同的签名),我猴子修补它们必须从不同的功能访问他们的常用方法。 简单地说,有可能发生,我想修补和根据不同的对象类型调用不同的补丁对象调度员。 修补器将方法添加到对象:
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
由于程序变得更复杂,使得周围的物体(或对象类)的包装似乎是更好的主意。 一些patchers共享公共代码或者是相互关联的。 但我不控制对象创建,也不是类创建。 我只得到了对象。 即使我能做到这一点,我只是想换行(或补丁)的特定对象,不是全部。
一种解决方案可能是一个基类添加到现有的对象,但我不知道如何维护和安全的,这是。 有另一种解决方案?
动态修改一个对象的类型是相当安全的,只要额外的基类是兼容的(你会得到一个异常,如果它不是)。 加入碱类的最简单的方法是使用3个参数的type
构造函数:
cls = object.__class__
object.__class__ = cls.__class__(cls.__name__ + "WithExtraBase", (cls, ExtraBase), {})
根据评论的另一个答案,这是另一种方式来修补的基类:
class Patched(instance.__class__, ExtraBase):
pass
instance.__class__ = Patched
一类添加到其他类基地,你可以这样做:
def pacher_of_some_type(object):
#this class holds all the stuff you want to add to the object
class Patch():
def target(self, value):
#do something
#add it to the class' base classes
object.__class__.__bases__ += (Patch, )
但是,这会影响这个类的所有对象和你实际改变类本身,这似乎并没有你想要的......如果你只是想修补的情况下,你可以继承原班和改变实例类动态:
class PatchedClass(object.__class__):
def target(self, value):
#do whatever
object.__class__ = PatchedClass
在安全性和可管理性方面,我会说,动态添加,因为你不太可能意外覆盖原始类的一些内部功能,因为新的基类增加是一个基类是为维护动态地增加了一些功能,更安全到元组的结束,这意味着它是最后使用的名称解析。 如果你真的想覆盖的方法,将它们添加到基类的元组的开始(当然这并不适用于子类的方法)。 不要问我,如果动态地改变类的实例是安全可言,但在一个简单的例子,似乎没有什么是一个问题:
class A():
def p(self): print 1
class B():
def p(self): print 2
a = A()
a.p() #prints 1
a.__class__ = B
a.p() #prints 2