简体   繁体   English

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

[英]Subclassing numpy.ndarray - why is __array_finalize__ not being called twice here?

According to this primer on subclassing ndarray , the __array_finalize__ method is guaranteed to be called, no matter if the subclass is instantiated directly, casted as a view or created from a template. 根据引物上的子类ndarray ,所述__array_finalize__方法保证被调用,不管亚类是直接实例化,铸造作为视图或从模板创建。

In particular, when calling the constructor explicitly, the order of methods called is __new__ -> __array_finalize__ -> __init__ . 特别是,显式调用构造函数时,称为方法的顺序是__new__ - > __array_finalize__ - > __init__

I have the following simple subclass of ndarray which allows an additional title attribute. 我有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

which produces the following output: 产生以下输出:

>>> 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'

As you can see, __array_finalize__ is being called as a result of the line 如您所见, __array_finalize__作为行的结果被调用

 self = input_array.view(Frame)

Question: why is __array_finalize__ not being called again as part of the __new__ -> __array_finalize__ -> __init__ chain? 问:为什么__array_finalize__不被再次调用的一部分__new__ - > __array_finalize__ - > __init__链?

In the documentation you link to, it describes how ndarray.__new__ will call __array_finalize__ on the arrays it constructs. 在您链接到的文档,它描述了如何ndarray.__new__将调用__array_finalize__它构建阵列。 And your class's __new__ method is causing that to happen when you create your instance as a view of an existing array. 当你将实例创建为现有数组的view时,你的类的__new__方法会导致这种情况发生。 The view method on the array argument is calling ndarray.__new__ for you, and it calls your __array_finalize__ method before the instance is returned to you. 数组参数的view方法为你调用ndarray.__new__ ,并在实例返回给你之前调用你的__array_finalize__方法。

You don't see __array_finalize__ called twice because you're not calling ndarray.__new__ a second time. 你没有看到__array_finalize__被调用两次,因为你没有第二次调用ndarray.__new__ If your __new__ method included a call to super().__new__ in addition to the view call, you probably would see __array_finalized__ called twice. 如果你的__new__方法除了view调用之外还包含对super().__new__的调用,你可能会看到__array_finalized__被调用两次。 Such behavior would probably be buggy (or at least, slower than necessary), so it's no surprise you're not doing it! 这样的行为可能是错误的(或者至少比必要的慢),所以你不会这样做也就不足为奇了!

Python doesn't automatically call overridden methods when the overriding subclass's method gets called. 当调用重写子类的方法时,Python不会自动调用重写方法。 It's up to the overriding method to call (or not call) the overridden version (directly with super or, as in this case, indirectly via another object's view method). 调用(或不调用)被覆盖的版本(直接使用super或,在本例中,通过另一个对象的view方法间接调用)取决于重写方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM