在Python中从另一个第三方模块重新定义类方法有多糟糕?
实际上,用户可以创建包含numbers with uncertainty的NumPy矩阵;理想情况下,我希望他们的代码运行不变(与代码操作浮点矩阵时相比);特别是,如果仍然可以使用m
获得矩阵m.I
的倒数,那将是很好的,尽管m.I
必须使用我自己的代码(原始I
来计算1}}方法通常不起作用。
重新定义numpy.matrix.I有多糟糕?首先,它确实篡改了我不喜欢的第三方代码,因为它可能不健壮(如果其他模块做同样的话会怎么样?...)。另一个问题是新的numpy.matrix.I是一个包装器,当实际应用原始的numpy.matrix.I以获得逆矩阵时,它会产生很小的开销。
是否继承了NumPy矩阵,只更改了I
方法?这将迫使用户更新他们的代码并创建具有m = matrix_with_uncert(…)
不确定性的数字矩阵(而不是保持使用numpy.matrix(…)
,如同浮点数矩阵),但这可能是一个不便之处应该被接受为了健壮?矩阵反演仍然可以用m.I
执行,这很好......另一方面,如果用户可以直接使用numpy.matrix()
构建所有矩阵(浮点数或具有不确定性的数字),那将是很好的,无需费心检查数据类型。
欢迎任何评论或其他方法!
答案 0 :(得分:11)
子类化(确实涉及覆盖,因为通常使用的术语)通常比“猴子修补”(将更改的方法填充到现有的类或模块中)更好,即使后者可用(内置类型,意思是用C语言实现的,可以保护自己免受猴子修补,而且大多数都可以保护自己。
例如,如果你的功能依赖于猴子修补,那么如果你猴子修补的课程在任何时候被升级为在C中实现(为了速度或专门防御猴子修补),它将会中断并停止升级。第三方软件包的维护者讨厌猴子修补,因为这意味着他们从不幸的用户那里得到了虚假的错误报告,他们(他们不知道)实际上正在使用一个破坏第三方软件包的有缺陷的猴子补丁,后者(除非破坏了猴子 - 明智的)是完美的。你已经注意到了可能的性能影响。
从概念上讲,“具有不确定性的数字矩阵”是与“数字矩阵”不同的概念。子类化表达这种干净,猴子修补尝试隐藏它。这实际上是一般情况下修补猴子的错误的根源:隐蔽的渠道通过全球隐藏的手段运作,没有清晰度和透明度。从这个根概念问题来看,所有许多实际问题都在某种意义上下降。
我强烈敦促您拒绝猴子修补,转而使用子类化等干净的解决方案。
答案 1 :(得分:1)
答案 2 :(得分:1)
取决于您对“重新定义”的意思。显然你可以使用自己的版本,没问题。如果它是一种方法,你也可以通过子类重新定义它。
您还可以创建一个新方法,并将其修补到类中,这种做法称为monkey_patching。像这样:
from amodule import aclass
def newfunction(self, param):
do_something()
aclass.oldfunction = newfunction
这将使所有aclass实例使用您的新函数而不是旧函数,包括任何“第四方”模块中的实例。这非常有用,但它被认为是非常丑陋和最后的选择。这是因为在类代码中没有任何内容表明您已覆盖该方法,因此很难调试。更糟糕的是,当两个模块monkeypatch相同的事情。那么你真的会感到困惑。