Вы не должны беспокоиться об этом, __Pyx_MemoryView_Len
так же быстро, как он получает, потому что он определен как:
typedef struct {
struct {{memview_struct_name}} *memview;
char *data;
Py_ssize_t shape[{{max_dims}}];
...
} {{memviewslice_name}};
// used for "len(memviewslice)"
#define __Pyx_MemoryView_Len(m) (m.shape[0])
Цвет этой строки не желтыйно желтоватый - что в основном означает, что это приводит не к чистому C-коду, а к тому, что используется некоторая функциональность _Pyx_XXX
, которая часто совсем не плоха для производительности.
Нет Python-взаимодействие - после прохождения C-препроцессора C-компилятор увидит, что вы написали:
return a.shape[0]
, что, кстати, приводит к белой линии.
Если вас также интересует размер многомерного memview, то этот SO-вопрос может стоить прочитать.
Annotate показывает определение функции в виде желтоголиния.Тем не менее, только стоимость, когда модуль загружен (и он оплачивается один раз, а не каждый раз при вызове функции), отвечает за «желтый» цвет.
Посмотрите на полученный C-код:
static int __pyx_f_9my_module_get_length(__Pyx_memviewslice __pyx_v_a) {
int __pyx_r;
__Pyx_RefNannyDeclarations
__Pyx_RefNannySetupContext("get_length", 0);
/* "my_module.pyx":5
*
* cdef int get_length(int[:] a):
* return a.shape[0] # <<<<<<<<<<<<<<
*/
__pyx_r = (__pyx_v_a.shape[0]);
goto __pyx_L0;
/* "my_module.pyx":4
* return 3. * a
*
* cdef int get_length(int[:] a): # <<<<<<<<<<<<<<
* return a.shape[0]
*/
/* function exit code */
__pyx_L0:;
__Pyx_RefNannyFinishContext();
return __pyx_r;
}
RefNannyXXXX
активен только при сборке с CYTHON_REFNANNY
-определенным.
Существует также другой код, показанный annotate
-инструментом, которыйсоответствует cdef int get_length(int[:] a):
:
/* … */
__pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_1);
if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(1, 1, __pyx_L1_error)
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
Однако этот код является частью __pyx_pymod_exec_XXXXX
/ PyInit_XXXXX
и вызывается только один раз, когда загружается модуль.На самом деле, я не уверен, как это связано с get_length
и зачем это нужно, но поскольку затраты настолько малы, я никогда не заботился о том, чтобы выяснить это.