这被称为“monkeypatching”,在某些情况下是完全合理的。
例如,如果您必须使用依赖于 的其他人的代码(您无法修改)SuperClass
,并且您需要更改该代码的行为,那么您唯一真正的选择是替换SuperClass
.
但是,在您的情况下,似乎没有任何充分的理由这样做。您正在定义 的所有子类SuperClass
,那么为什么不在两者之间添加另一个类呢?
class Intermediate(SuperClass):
def func3():
pass
class SubClass1(Intermediate):
def func1():
print 'hi'
SuperClass
如果您无法控制的其他代码需要该功能,这对于“应该存在但没有的功能”来说还不够好......但是当只有您的代码需要该功能时,它同样好,而且很多更简单。
如果连子类都不受您的控制,通常您可以从每个. 例如:
class Func3Mixin(object):
def func3():
pass
class F3SubClass1(SubClass1, Func3Mixin):
pass
class F3SubClass2(SubClass2, Func3Mixin):
pass
现在您只需构造实例F3SubClass1
而不是SubClass1
. 期望SubClass1
实例的代码可以使用F3SubClass1
就好了。而 Python 的鸭子类型使得这种“面向 mixin 的编程”特别简单:在 的实现中Func3Mixin.func3
,你可以使用 的属性和方法SuperClass
,尽管它Func3Mixin
本身并没有以SuperClass
任何方式静态相关,因为你知道任何作为 a 的运行时对象Func3Mixin
也将是SuperClass
.
同时,即使猴子补丁是合适的,它也不一定是最好的答案。例如,如果您正在修补以解决某些第三方代码中的错误,该代码有一个很好的许可证和一个源存储库,可以轻松维护自己的补丁,您可以只分叉它,创建一个固定副本,并使用它来代替原来的。
此外,值得指出的是,您的任何类实际上都不能像编写的那样使用——任何调用任何方法的尝试都会引发 a TypeError
,因为它们缺少self
参数。但是你用猴子补丁的方式func3
,它会以完全相同的方式失败func1
。(我上面勾勒的替代方案也是如此。)
最后,这里所有的类都是经典类而不是新式的,因为你忘记了SuperClass
继承自object
。如果你不能改变SuperClass
,当然,这不是你的错——但你可能想通过让你的子类(或Intermediate
)乘以继承object
来修复它SuperClass
。(如果您一直在关注:是的,这意味着您可以混入新式类。尽管在幕后您必须了解元类才能理解原因。)