我已经找到了numpy.ma.where()函数的源代码,但它似乎正在调用numpy.where)函数,为了更好地理解它,如果可能的话,我想看看。
大多数Python函数都是用Python语言编写的,但有些函数是用更原生的语言(通常是C语言)编写的。
正则Python函数("纯Python")
有一些技术可以用来询问Python本身在哪里定义了函数。可能最便携的使用inspect
模块:
>>> import numpy
>>> import inspect
>>> inspect.isbuiltin(numpy.ma.where)
False
>>> inspect.getsourcefile(numpy.ma.where)
'.../numpy/core/multiarray.py'
但这不适用于本机("内置")功能:
>>> import numpy
>>> import inspect
>>> inspect.isbuiltin(numpy.where)
True
>>> inspect.getsourcefile(numpy.where)
TypeError: <built-in function where> is not a module, class, method, function, traceback, frame, or code object
本机("内置")功能
不幸的是,Python没有为内置函数提供源文件的记录。您可以找到哪个模块提供功能:
>>> import numpy as np
>>> np.where
<built-in function where>
>>> np.where.__module__
'numpy.core.multiarray'
Python不会帮助您找到该模块的本机(C)源代码,但在这种情况下,在numpy项目中查找具有类似名称的C源代码是合理的。我发现了以下文件:
numpy/core/src/multirarray/multiarraymodule.c
在那个文件中,我发现了一个定义列表(PyMethodDef
),其中包括:
{"where",
(PyCFunction)array_where,
METH_VARARGS, NULL},
这表明C函数array_where
就是Python认为的"where"
。
array_where
函数是在同一个文件中定义的,它主要委托给PyArray_Where
函数。
简而言之
NumPy的np.where
函数是用C编写的,而不是用Python编写的。PyArray_Where是个不错的地方。
首先有两个不同版本的where
,一个只使用condition
,另一个使用3个数组。
更简单的一个是最常用的,它只是np.nonzero
的另一个名称。这将扫描condition
阵列两次。一旦使用np.count_nonzero
来确定有多少非零条目,这允许它分配返回数组。第二步是填充所有非零条目的坐标。关键是它返回一个数组元组,condition
的每个维度都有一个数组。
condition, x, y
版本采用三个阵列,它们相互广播。返回数组具有常见的广播形状,元素从x
和y
中选择,如您之前的问题"numpy.where()是如何选择本例中的元素的?
您确实意识到,这些代码中的大部分都是c
或cython
,其中有一个重要的预处理部分。它很难阅读,即使对于有经验的用户来说也是如此。运行各种测试用例并以这种方式了解正在发生的事情更容易。
有几件事需要注意。np.where
是一个python函数,python在将每个输入传递给它之前对其进行完全求值。这是条件赋值,而不是条件求值函数。
除非你通过3个形状匹配的数组,或者标量x
和y
,否则你需要对广播有很好的理解。
您可以在numpy.core.multirarray 中找到代码
C:Users<name>AppDataLocalProgramsPythonPython37-32Libsite-packagesnumpycoremultiarray.py
是我找到它的地方。