举一个简单的例子,以一个类为例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
按价值x
,即返回值p(x)
。但不是以这种方式调用函数,而是调用p.evaluate(x)
(或者更直观地p(x)
via __call__ http://docs.python.org/2/reference/datamodel.html#emulating-callable-objects) 会更好。但应该怎么做呢?
a) 猴子补丁,即
Polynomial.evaluate = horner.evaluate_polynomial
# or Polynomial.__call__ = horner.evaluate_polynomial
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
果然,猴子补丁是最短的(特别是因为我没有包含任何检查)hasattr(Polynomial, 'evaluate')
,但类似地,子类应该调用super()
那么...),但它是最 Pythonic 的吗?或者还有其他更好的选择吗?
特别是考虑多个插件提供相同功能的可能性,例如zeros
要么使用numpy
或者自制的二分法,当然只应该使用一个实现插件,哪种选择可能不太容易出错?