2011-11-10 9 views
8

uczę Cython i natknąłem się na to snippit kodu:Cython: bo od 1 <= i <n

import numpy as np 
cimport numpy as np 

def mean(np.ndarray[np.double_t] input): 

    cdef np.double_t cur 
    # Py_ssize_t is numpy's index type 
    cdef Py_ssize_t i 
    cdef Py_ssize_t N = len(input) 

    for i from 0 <= i < N: 
     cur += input[i] 

    return cur/N 

a=np.array([1,2,3,4], dtype=np.double) 

Oczywiście, to zwraca średnią który wynosi 2,5. Moje pytanie jest następujące:

Czy pętla for jest pętlą w języku Python, Cythonem lub C?

Odpowiedz

5

Skompiluj i zobacz: kod C, który tworzy Cython, jest ładnie opisany.

/* "cyexample.pyx":11 
*  cdef Py_ssize_t N = len(input) 
* 
*  for i from 0 <= i < N:    # <<<<<<<<<<<<<< 
*   cur += input[i] 
* 
*/ 
    __pyx_t_1 = __pyx_v_N; 
    for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_1; __pyx_v_i++) { 
    /* "cyexample.pyx":12 
* 
*  for i from 0 <= i < N: 
*   cur += input[i]    # <<<<<<<<<<<<<< 
* 
*  return cur/N 
*/ 
    __pyx_t_2 = __pyx_v_i; 
    __pyx_t_3 = -1; 
    if (__pyx_t_2 < 0) { 
     __pyx_t_2 += __pyx_bshape_0_input; 
     if (unlikely(__pyx_t_2 < 0)) __pyx_t_3 = 0; 
    } else if (unlikely(__pyx_t_2 >= __pyx_bshape_0_input)) __pyx_t_3 = 0; 
    if (unlikely(__pyx_t_3 != -1)) { 
     __Pyx_RaiseBufferIndexError(__pyx_t_3); 
     {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;} 
    } 
    __pyx_v_cur = (__pyx_v_cur + (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_bstruct_input.buf, __pyx_t_2, __pyx_bstride_0_input))); 
    } 

A więc sama pętla zostanie pomyślnie przekształcony C. Zauważ, że te dni mogą obsługiwać Cython strzelnica naturalnie, więc starszy „od 0 < = i < N” styl nie jest konieczne. Punktem wprowadzenia składni "do/z" (nie-Python) było oznaczenie, które pętle powinny być C-ified.

+0

I tak niektóre naiwnych testy timeit i obie struktury pętli wydaje się działać w tym samym czasie z wielkości tablicy duże. Czy ktoś może to potwierdzić? Ciekawi mnie tylko, dlaczego autor tego konkretnego snippada zdecydował się na użycie starszej struktury we współczesnym kodzie. –

+1

Powrót w dzień, Cython nie zoptymalizowałby 'for i in range (10)', więc faktycznie tworzyłby listę o długości 10 i iteruje nad nią za pomocą wywołań Pythona. Z tego powodu Pyrex/Cython wprowadził składnię ... z ..., która sprowadzałaby się do C. Czasami wciąż używam starszej składni, ponieważ jest bardziej jasne, że ten kod jest zoptymalizowany. – carl