如何查看numpy.array()源码?

问题描述:在使用numpy是,很好奇下面这段代码是怎么实现的。

import numpy as np

x = np.array([1,2,3])

于是花了点时间来探索,这里记录一下。

在IDE里点开`array`,跳转到一个`_multiarray_umath.pyi`的文件中,这个文件写的密密麻麻,看的一头雾水。如下:

def array(object, dtype=..., *, copy=..., order=..., subok=..., ndmin=..., like=...) -> typing.Any:
    "array(object, dtype=None, *, copy=True, order='K', subok=False, ndmin=0,\n          like=None)\n\n    Create an array.\n\n    Parameters\n    ----------\n    object : array_like\n..."

实际上这里只有对`array`的解释说明,并没有源码。因为`.pyi`文件中只存放对函数或类的文档,方便从IDE中查看函数的使用说明。
点开`np`,跳转到`numpy.__init__`文件中,去搜索`array`,只发现在注释中出现了`array`,在代码中一点也没有出现。检查该文件的引用,发现有以下几行代码:

from .core import *
from .lib import *
from .matrixlib import *
__all__.extend(core.__all__)
__all__.extend(_mat.__all__)
__all__.extend(lib.__all__)

在python中,`__all__`限制了`from XX import *` 的范围,上述引用方式只会显示`__all__`中的模块名。也就是说`__init__`中肯定存在`array`,既然没有显示的找到它,那么一定是引用自其他文件的`__all__`变量。首先查找`.core.__init__`,一看这里这么多`*`,这可咋找?

from .numeric import *
from . import fromnumeric
from .fromnumeric import *
from . import defchararray as char
from . import records as rec
from .records import *
from .memmap import *
from .defchararray import chararray
from . import function_base
from .function_base import *
from . import machar
from .machar import *
from . import getlimits
from .getlimits import *
from . import shape_base
from .shape_base import *
from . import einsumfunc
from .einsumfunc import *

网上搜索下了,`numeric`里有绝大部分numpy方法的实现,去看一下`numeric.py`文件,发现有这样一句话:

from .multiarray import (
    _fastCopyAndTranspose as fastCopyAndTranspose, ALLOW_THREADS,
    BUFSIZE, CLIP, MAXDIMS, MAY_SHARE_BOUNDS, MAY_SHARE_EXACT, RAISE,
    WRAP, arange, array, broadcast, can_cast, compare_chararrays,
    concatenate, copyto, dot, dtype, empty,
    empty_like, flatiter, frombuffer, fromfile, fromiter, fromstring,
    inner, int_asbuffer, lexsort, matmul, may_share_memory,
    min_scalar_type, ndarray, nditer, nested_iters, promote_types,
    putmask, result_type, set_numeric_ops, shares_memory, vdot, where,
    zeros, normalize_axis_index)

终于找到了`array`这个单词。。。为啥说是个单词呢?因为只是看到了`array`,并没有看到它的定义。接着去`.multiarray`里找,发现如下语句:

from numpy.core._multiarray_umath import *
from numpy.core._multiarray_umath import (
    _fastCopyAndTranspose, _flagdict, _insert, _reconstruct, _vec_string,
    _ARRAY_API, _monotonicity, _get_ndarray_c_version
    )

__all__ = [
    '_ARRAY_API', 'ALLOW_THREADS', 'BUFSIZE', 'CLIP', 'DATETIMEUNITS',
    'ITEM_HASOBJECT', 'ITEM_IS_POINTER', 'LIST_PICKLE', 'MAXDIMS',
    'MAY_SHARE_BOUNDS', 'MAY_SHARE_EXACT', 'NEEDS_INIT', 'NEEDS_PYAPI',
    'RAISE', 'USE_GETITEM', 'USE_SETITEM', 'WRAP', '_fastCopyAndTranspose',
    '_flagdict', '_insert', '_reconstruct', '_vec_string', '_monotonicity',
    'add_docstring', 'arange', 'array', 'bincount', 'broadcast',
    'busday_count', 'busday_offset', 'busdaycalendar', 'can_cast',
    'compare_chararrays', 'concatenate', 'copyto', 'correlate', 'correlate2',
    'count_nonzero', 'c_einsum', 'datetime_as_string', 'datetime_data',
    'digitize', 'dot', 'dragon4_positional', 'dragon4_scientific', 'dtype',
    'empty', 'empty_like', 'error', 'flagsobj', 'flatiter', 'format_longfloat',
    'frombuffer', 'fromfile', 'fromiter', 'fromstring', 'inner',
    'int_asbuffer', 'interp', 'interp_complex', 'is_busday', 'lexsort',
    'matmul', 'may_share_memory', 'min_scalar_type', 'ndarray', 'nditer',
    'nested_iters', 'normalize_axis_index', 'packbits',
    'promote_types', 'putmask', 'ravel_multi_index', 'result_type', 'scalar',
    'set_datetimeparse_function', 'set_legacy_print_mode', 'set_numeric_ops',
    'set_string_function', 'set_typeDict', 'shares_memory', 'test_interrupt',
    'tracemalloc_domain', 'typeinfo', 'unpackbits', 'unravel_index', 'vdot',
    'where', 'zeros']

这里,在`__all__`字段里找到了`array`,这应该就是我们能在python中找到的最原始的引用了,除此之外再没有其他的关于`array`的定义了。

注意到上面还有一句话是:

from numpy.core._multiarray_umath import *

这个`_multiarray_umath`很眼熟,和最开始在IDE里点开`array`跳转到的文件很像。查看了下`numpy.core`目录,有一个动态链接库文件,在windows中是`_multiarray_umath.cp38-win_amd64.pyd`,在linux中是`_multiarray_umath.cpython-38-x86_64-linux-gnu.so`。
okay,也就是说,`array`是C语言编译后引入的,在我们已经安装的包中是看不到源码的。

那么它具体是从哪里编译过来的呢?
在网上找到了答案:
在这个文件中有它的源码`numpy/core/src/multiarray/multiarraymoudle.c`
搜索`"array"`,注意加双引号,不然只搜索`array`的话有1000多个结果。找到下面这句话:

{"array",
	(PyCFunction)_array_fromobject,
	METH_VARARGS|METH_KEYWORDS, NULL},

意思就是在python中引用的名字叫`array`,是C里面`_array_fromobject`这个函数。在同一个文件里找到这个函数:

static PyObject *
_array_fromobject(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws)
{
    PyObject *op;
    PyArrayObject *oparr = NULL, *ret = NULL;
    npy_bool subok = NPY_FALSE;
    npy_bool copy = NPY_TRUE;
    int ndmin = 0, nd;
    PyArray_Descr *type = NULL;
    PyArray_Descr *oldtype = NULL;
    NPY_ORDER order = NPY_KEEPORDER;
    int flags = 0;
    ...
}

这就是np.array()真正的源码了,里面用了很多C类型,慢慢研究吧。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值