在寻找一个不起眼的错误时,我偶然发现了这个最小示例最能证明的东西:
import numpy as np
class First(object):
def __init__(self):
self.vF = np.vectorize(self.F)
print "First: vF = ", self.vF
def F(self, x):
return x**2
class Second(First):
def __init__(self):
super(Second, self).__init__()
print "Second: vF = ", self.vF
def F(self, x):
raise RuntimeError("Never be here.")
def vF(self, x):
return np.asarray(x)*2
我希望
Second
的实例具有明确定义的 vF
方法,但情况似乎并非如此:arg = (1, 2, 3)
f = First()
print "calling first.vF: ", f.vF(arg)
s = Second()
print "calling second.vF: ", s.vF(arg)
产生
First: vF = <numpy.lib.function_base.vectorize object at 0x23f9310>
calling first.vF: [1 4 9]
First: vF = <numpy.lib.function_base.vectorize object at 0x23f93d0>
Second: vF = <numpy.lib.function_base.vectorize object at 0x23f93d0>
calling second.vF:
Traceback (most recent call last):
...
RuntimeError: Never be here.
这样看来
s.vF
和 f.vF
是同一个对象,即使 s.vF == f.vF
是 False
。这是预期的/已知的/记录在案的行为,并且
numpy.vectorize
不能很好地与继承配合使用,还是我在这里遗漏了一些简单的东西?(当然,在这种特殊情况下,通过将
First.vF
更改为普通的 Python 方法,或者只是不在 super
的构造函数中调用 Second
,问题很容易解决。) 最佳答案
这与 NumPy 无关。这是完全合理的语言设计决策(以及您决定使用语言的方式)相互作用的结果:
self.F
工作的绑定(bind)方法)。 结合起来,这些完全合理的行为可能会产生意想不到的行为,如果您不牢记细节而是使用简化的心智模型(例如,心智分离方法和“数据”属性)。详细地说,这发生在您的示例中:
First.__init__
,要么是立即调用 Second.__init__
的 First.__init__
。 obj.vF
始终是在 First.__init__
中为所有 obj
创建的向量化函数。 self.F
。在第二个对象的情况下,这是 RuntimeError
提升 Second.F
。 您可能应该在这里只使用常规的
vF
方法,因为由于属性查找的工作方式,这允许子类轻松覆盖(另请参阅:MRO)。关于python - 继承 numpy.vectorize 函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14859840/