2016-09-27 104 views
3

根据this的子类ndarray的底层引擎,保证调用__array_finalize__方法,无论子类是直接实例化,作为视图转换还是从模板创建。Subclassing numpy.ndarray - 为什么__array_finalize__在这里没有被调用两次?

特别是,当明确调用构造函数时,调用方法的顺序是__new____array_finalize____init__

我有以下简单的子类ndarray它允许额外的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__链的一部分?

+0

我会认为这是因为'__array_finalize__'每个对象只调用一次。 numpy知道你的'self'已经调用了__array_finalize__',所以它不会再调用它。不确定你指的是哪一个例子,但是当我在该页面的RealisticInfoArray例子中加入一些'print'调用时,'__array_finalize__'只被调用一次。我也看不到它在那个页面上的位置,它暗示了你提到的新的 - > finalize - > init命令,或者你为什么认为它会调用终结器两次。 – BrenBarn

+0

@BrenBarn我的想法是,从[this]的输出中按顺序调用方法(http://docs.scipy.org/doc/numpy/user/basics.subclassing.html#the-role-of -array-finalize)部分,其中该示例具有所有三种方法,并且因为文本提及“'ndarray .__ new__”将“__array_finalize__”传递给新对象。所以我很好奇为什么我的'__new__'方法似乎没有这样做。我的例子本身来自[this](http://docs.scipy.org/doc/numpy/user/basics.subclassing.html#slightly-more-realistic-example-attribute-added-to-existing-array)部分。 – timgeb

回答

1

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

您没有看到__array_finalize__调用了两次,因为您没有再次调用ndarray.__new__。如果您的__new__方法除了呼叫view之外还包含对super().__new__的呼叫,您可能会看到__array_finalized__呼叫两次。这样的行为可能会有问题(或者至少比必要的慢),所以毫无疑问你不会这么做!

当覆盖子类的方法被调用时,Python不会自动调用覆盖方法。取决于重写方法调用(或不调用)被覆盖的版本(直接与super或在这种情况下,通过另一个对象的view方法间接)。

+0

我不知道怎么处理'ndarray''__new__'方法是'__array_finalize__'的罪魁祸首,并且它不是由于一些魔法而发生的。谢谢。 – timgeb

相关问题