简体   繁体   English

什么(numpy)__array_wrap__呢?

[英]What does (numpy) __array_wrap__ do?

I am diving into the SciPy LinAlg module for the first time, and I saw this function: 我第一次潜入SciPy LinAlg模块,我看到了这个功能:

def _makearray(a):
    new = asarray(a)
    wrap = getattr(a, "__array_prepare__", new.__array_wrap__)
    return new, wrap

What does __array_wrap__ do exactly? __array_wrap__到底做了什么? I found the documentation , but I don't understand this explanation: 我找到了文档 ,但我不明白这个解释:

 At the end of every ufunc, this method is called on the input object with the
 highest array priority, or the output object if one was specified. The ufunc-
 computed array is passed in and whatever is returned is passed to the user. 
 Subclasses inherit a default implementation of this method, which transforms the
 array into a new instance of the object’s class. Subclasses may opt to use this
 method to transform the output array into an instance of the subclass and update
 metadata before returning the array to the user.

Does this just mean it reconverts the output of whatever function back into an array since it was likely broken up into something else for element-by-element processing? 这是否意味着它将任何函数的输出重新转换回array因为它可能被分解为其他元素以进行逐元素处理? Relatedly, regardless of the explanation, what would it mean to get this wrap as an object? 相关地,无论解释如何,将此wrap作为对象意味着什么? What would you do with it? 你会怎么做?

I am looking at the code for numpy.linalg.inv ...what is wrap doing here? 我正在查看numpy.linalg.inv的代码...这里的包装是什么?

    **a, wrap = _makearray(a)**
    _assertRankAtLeast2(a)
    _assertNdSquareness(a)
    t, result_t = _commonType(a)

    if a.shape[-1] == 0:
        # The inner array is 0x0, the ufunc cannot handle this case
        **return wrap(empty_like(a, dtype=result_t))**

    signature = 'D->D' if isComplexType(t) else 'd->d'
    extobj = get_linalg_error_extobj(_raise_linalgerror_singular)
    ainv = _umath_linalg.inv(a, signature=signature, extobj=extobj)
    return wrap(ainv.astype(result_t))

np.ma.masked_array.__array_wrap__ is an example of a array subclass that updates the metadata (the mask ). np.ma.masked_array.__array_wrap__是更新元数据( mask )的数组子类的示例。

File:        /usr/lib/python3/dist-packages/numpy/ma/core.py
Definition:  np.ma.masked_array.__array_wrap__(self, obj, context=None)
Source:
    def __array_wrap__(self, obj, context=None):
        """
        Special hook for ufuncs.
        Wraps the numpy array and sets the mask according to context.
        """

np.matrix.__array_wrap__ appears to inherit the ndarray version. np.matrix.__array_wrap__似乎继承了ndarray版本。 My guess it's because matrix , while a subclass, does not have metadata that needs updating. 我的猜测是因为matrix虽然是子类,但没有需要更新的元数据。

Generally the idea with a hook , is that it's a function that is called deep within the normal processing. 通常使用hook的想法是,它是在正常处理中被深度调用的函数。 The default method might not do anything. 默认方法可能不会执行任何操作。 But it's a way that the subclass can take special action. 但这是子类可以采取特殊操作的方式。 The class developer writes hooks like this so that the class user will not have to worry about those details. 类开发人员编写这样的钩子,以便类用户不必担心这些细节。 With a __...__ name it isn't part of the public interface - though Python lets us peak under the curtain. 使用__...__名称它不是公共接口的一部分 - 尽管Python让我们在幕后巅峰。

An example of wrapping , ie returning an array with the same class as the inputs is: wrapping一个例子,即返回与输入具有相同类的数组是:

In [659]: np.cumsum(np.arange(10))
Out[659]: array([ 0,  1,  3,  6, 10, 15, 21, 28, 36, 45], dtype=int32)

In [660]: np.cumsum(np.matrix(np.arange(10)))
Out[660]: matrix([[ 0,  1,  3,  6, 10, 15, 21, 28, 36, 45]], dtype=int32

In [665]: np.cumsum(np.ma.masked_array(np.arange(10)))
Out[665]: 
masked_array(data = [ 0  1  3  6 10 15 21 28 36 45],
             mask = False,
       fill_value = 999999)

The returned values are all the same, but the array subclass varies, depending on the input class. 返回的值都是相同的,但数组子类会有所不同,具体取决于输入类。


cumsum might not be the best example. cumsum可能不是最好的例子。 Masked arrays have their own version of cumsum , one that treats the masked values as 0 : 蒙面数组有自己的cumsum版本,一个将屏蔽值视为0

In [679]: m=np.ma.masked_array(np.arange(10),np.arange(10)%2)

In [680]: m
Out[680]: 
masked_array(data = [0 -- 2 -- 4 -- 6 -- 8 --],
             mask = [False  True False  True False  True False  True False  True],
       fill_value = 999999)

In [681]: np.cumsum(m)
Out[681]: 
masked_array(data = [0 -- 2 -- 6 -- 12 -- 20 --],
             mask = [False  True False  True False  True False  True False  True],
       fill_value = 999999)

add.accumulate is similar to cumsum , but doesn't have a special masked version: add.accumulate类似于cumsum ,但没有专门的蒙面版本:

In [682]: np.add.accumulate(np.arange(10))
Out[682]: array([ 0,  1,  3,  6, 10, 15, 21, 28, 36, 45], dtype=int32)

In [683]: np.add.accumulate(m)
Out[683]: 
masked_array(data = [ 0  1  3  6 10 15 21 28 36 45],
             mask = False,
       fill_value = 999999)

This last is a masked array, but the mask is the default False , and the masked values were included in the sum. 最后一个是掩码数组,但掩码是默认的False ,掩码值包含在总和中。

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

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