根据关于子类ndarray
的{{3}}引子,无论子类是直接实例化,作为视图转换还是从模板创建,都可以保证调用__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__
- &gt;再次调用__array_finalize__
- &gt; __init__
链?
答案 0 :(得分:2)
在您链接到的文档中,它描述了ndarray.__new__
如何在其构造的阵列上调用__array_finalize__
。当您将实例创建为现有数组的__new__
时,您的类的view
方法会导致这种情况发生。数组参数的view
方法为您调用ndarray.__new__
,并在实例返回给您之前调用__array_finalize__
方法。
您没有看到__array_finalize__
被叫两次,因为您没有再次呼叫ndarray.__new__
。如果__new__
方法除super().__new__
来电之外还包含对view
的调用,您可能会看到__array_finalized__
被调用两次。这样的行为可能是错误的(或者至少比必要的慢),所以你不会这样做也就不足为奇了!
当调用重写子类的方法时,Python不会自动调用重写方法。调用(或不调用)被覆盖的版本(直接使用super
或者在本例中间接通过另一个对象的view
方法)取决于重写方法。