举个简单的例子,上课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)
来评估 value 的实例Polynomial
,即返回 的值。但是,与其以这种方式调用函数,不如调用(或更直观地通过)会更好。但是应该怎么做呢?p
x
p(x)
p.evaluate(x)
p(x)
__call__
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) Mixin + 替换,即
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 à la hasattr(Polynomial, 'evaluate')
,但类似的子类应该调用super()
then...),但它是最 Pythonic 的吗?还是有其他更好的选择?
特别是考虑到多个插件提供相同功能的可能性,例如zeros
使用numpy
或自制二分法,当然应该只使用一个实现插件,哪种选择可能更不容易出错?