作为一个简单的例子,以一个类Polynomial
class Polynomial(object):
def __init__(self, coefficients):
self.coefficients = coefficients
对于p(x) = a_0 + a_1*x + a_2*x^2 + ... + a_n*x^n
形式的多项式,其中列表coefficients = (a_0, a_1, ..., a_n)
存储这些系数。在
一个插件模块horner
可以提供一个函数horner.evaluate_polynomial(p, x)
来计算Polynomial
实例{p.evaluate(x)
(或者更直观地说,p(x)
通过^{
a)猴子修补,即
^{pr2}$b)子类化和替换类,即
orgPolynomial = Polynomial
class EvaluatablePolynomial(Polynomial):
def evaluate(self, x):
return horner.evaluate_polynomial(self, x)
Polynomial = EvaluatablePolynomial
c)混合+更换,即
orgPolynomial = Polynomial
class Evaluatable(object):
def evaluate(self, x):
return horner.evaluate_polynomial(self, x)
class EvaluatablePolynomial(Polynomial, Evaluatable):
pass
Polynomial = EvaluatablePolynomial
果然,monkey-patching是最短的一个(尤其是我没有包括check-alahasattr(Polynomial, 'evaluate')
,但是类似地,一个子类应该调用super()
),但是它是最具python特性的吗?或者还有其他更好的选择吗?在
特别是考虑到多个插件提供相同功能的可能性,例如zeros
要么使用numpy
要么使用自制的二等分法,当然只应该使用一个实现插件,哪种选择可能不那么容易出错?在
monkey将函数直接修补到原始类而不是替换它的一个最重要的特性是,在加载插件之前对原始类的/实例的引用现在也将具有新的属性。在给定的示例中,这很可能是期望的行为,因此应该使用。在
但是,也可能存在其他情况,即monkey patch以与原始实现不兼容的方式修改现有方法的行为,并且修改后的类的以前实例应该使用原始实现。当然,这不仅是罕见的,而且是糟糕的设计,但你应该记住这种可能性。由于一些复杂的原因,代码甚至可能依赖于monkey-patch-added方法的缺失,尽管这里似乎很难想出一个非人工的例子。在
总之,除了少数例外,monkey将方法修补到原始类中(最好在修补之前进行
hasattr(...)
检查)应该是首选方法。在编辑我当前的go:创建一个子类(用于更简单的代码完成和修补),然后使用以下
patch(patching_class, unpatched_class)
方法:悬而未决的问题是,相应的子类的module是应该在导入时直接调用
patch
,还是应该手动调用。我也在考虑为这样一个修补子类编写一个装饰器或元类。。。在相关问题 更多 >
编程相关推荐