python - 子类化 numpy.ndarray - 为什么 __array_finalize__ 在这里没有被调用两次?

标签 python numpy inheritance

根据 this ndarray 的子类入门,__array_finalize__ 方法保证被调用,无论子类是直接实例化、转换为 View 还是从模板创建。

特别是显式调用构造函数时,方法调用顺序为__new__ -> __array_finalize__ -> __init__

我有以下 ndarray 的简单子(monad)类,它允许额外的 title 属性。

class Frame(np.ndarray):    
    def __new__(cls, input_array, title='unnamed'):
        print 'calling Frame.__new__ with title {}'.format(title)
        self = input_array.view(Frame) # does not call __new__ or __init__
        print 'creation of self done, setting self.title...'
        self.title = title
        return self

    def __array_finalize__(self, viewed):
        # if viewed is None, the Frame instance is being created by an explicit
        # call to the constructor, hence Frame.__new__ has been called and the
        # title attribute is already set
        #
        # if viewed is not None, the frame is either being created by view
        # casting or from template, in which case the title of the viewed object
        # needs to be forwarded to the new instance
        print '''calling Frame.__array_finalize__ with type(self) == {} and
        type(viewed) == {}'''.format(type(self), type(viewed))

        if viewed is not None:
            self.title = getattr(viewed, 'title', 'unnamed')

        print self.title

产生以下输出:

>>> f = Frame(np.arange(3), 'hallo')
calling Frame.__new__ with title hallo
calling Frame.__array_finalize__ with type(self) == <class '__main__.Frame'> and
        type(viewed) == <type 'numpy.ndarray'>
unnamed
creation of self done, setting self.title...
>>> f.title
'hallo'

如您所见,__array_finalize__ 作为该行的结果被调用

 self = input_array.view(Frame)

问题:为什么 __array_finalize__ 不再作为 __new__ 的一部分被调用 -> __array_finalize__ -> __init__ 链?

最佳答案

在您链接到的文档中,它描述了 ndarray.__new__ 将如何在其构造的数组上调用 __array_finalize__。当您将实例创建为现有数组的 view 时,您的类的 __new__ 方法会导致这种情况发生。数组参数上的 view 方法正在为您调用 ndarray.__new__,它会在实例返回给您之前调用您的 __array_finalize__ 方法。

您没有看到 __array_finalize__ 被调用两次,因为您没有第二次调用 ndarray.__new__。如果您的 __new__ 方法除了 view 调用之外还包含对 super().__new__ 的调用,您可能会看到 __array_finalized__ 调用了两次。这种行为可能会出现错误(或者至少比必要的慢),所以您不这样做也就不足为奇了!

当覆盖子类的方法被调用时,Python 不会自动调用被覆盖的方法。调用(或不调用)覆盖版本(直接使用 super 或在本例中,通过另一个对象的 view 方法间接调用)取决于覆盖方法。

关于python - 子类化 numpy.ndarray - 为什么 __array_finalize__ 在这里没有被调用两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39732213/

相关文章:

python - 如何过滤数据框中的行?

python - emacs 中 python 代码折叠的范围

python - 查找 NumPy 数组中大于 N 的值的开始/停止索引范围

c++ - 从父方法调用子方法

python - 在 Numpy C 扩展中返回可变长度数组?

python - 无法创建第二个数据框 python pandas

python - 如何在 NumPy 中声明和填充数组?

python - 使用条件拆分多维 numpy 数组

c++ - 知道基类指针指向哪个派生类

javascript - 如何继承DOM元素类