Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 继承numpy.vectorize-ed函数_Python_Numpy - Fatal编程技术网

Python 继承numpy.vectorize-ed函数

Python 继承numpy.vectorize-ed函数,python,numpy,Python,Numpy,在寻找一个模糊的bug时,我偶然发现了一个最能说明问题的例子: 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 __in

在寻找一个模糊的bug时,我偶然发现了一个最能说明问题的例子:

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.
First:vF=
呼叫first.vF:[1 4 9]
第一:vF=
第二:vF=
调用second.vF:
回溯(最近一次呼叫最后一次):
...
RuntimeError:永远不要在这里。
因此,似乎
s.vF
f.vF
是同一个对象,即使
s.vF==f.vF
False

这是一种预期的/已知的/文档化的行为,并且
numpy.vectorize
不能很好地处理继承,还是我缺少了一些简单的东西?
(当然,在这种特殊情况下,通过将
First.vF
更改为普通的Python方法,或者只是不在
第二个
的构造函数中调用
super
,问题很容易解决。)

这与
numpy无关。矢量化
numpy
通常真的


这里发生的是
Second.\uuuu init\uuuuu
首先调用
。\uuuu init\uuuuu
self.F
(实际上是围绕
Second.F
的实例方法包装器)创建一个实例属性(
vF
),并将其作为
vF
存储在实例上。现在,当您查找
vF
时,您得到的是猴子补丁版本,而不是原始实例方法
Second。vF

这与NumPy无关。这是完全合理的语言设计决策(以及您决定使用语言的方式)相互作用的结果:

  • 实例属性优先于类属性。我相信你会同意这是合理的
  • 方法是类属性,在这一点上并不特殊。我相信您会同意这是合理的(如果您不同意,请查看描述符,特别是允许
    self.F
    工作的绑定方法)
  • 继承的实例属性附加到同一个对象,而不是附加到某个奇怪的“父代理”对象或其他对象。我相信你会同意这是合理的
总之,如果您不考虑细节,而是使用简化的心智模型(例如,心智隔离方法和“数据”属性),这些完全合理的行为可能会产生意外的行为。具体来说,在您的示例中会发生这种情况:

  • 调用相应的构造函数。这要么是
    First.\uuuu init\uuu
    ,要么是
    Second.\uuuu init\uuu
    ,它立即调用
    First.\uuuu init\uu
  • 因此,
    obj.vF
    始终是首先在
    中创建的矢量化函数。\uuu init\uuu
    用于所有
    obj
  • 但是,每个对象的矢量化函数包装了各自对象的
    self.F
    。对于第二个对象,这是
    运行时错误
    -引发
    second.F
您可能应该在这里使用一个常规的
vF
方法,因为由于属性查找的工作方式,这允许子类轻松地重写(另请参见:MRO)