Cython efficient cycle 'for' for a given list instead of range(N)
<p>I'm coding on cython (python 2.7) and I'm dealing with 'for' cycles. As long as I use the standard <code>for i in range(N)</code>, I got a cool code: no yellow warning on the cythonized <code>code.html</code>.</p>

<p>When I create a list of integer (as range(N) is, isn't it?), for example:</p>

<pre><code>cdef long [:] lista = np.array(list(nx.node_connected_component(Graph, v)))
</code></pre>

<p>which gives me the list of all indices of the nodes in the connected component of <code>v</code> in the graph <code>Graph</code>. I got a yellow warning when I try to define <code>for i in lista:</code>:</p>

<pre><code>  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_lista, 1, (PyObject *(*)(char *)) __pyx_memview_get_long, (int (*)(char *, PyObject *)) __pyx_memview_set_long, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 151, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
    __pyx_t_6 = __pyx_t_1; __Pyx_INCREF(__pyx_t_6); __pyx_t_15 = 0;
    __pyx_t_17 = NULL;
  } else {
    __pyx_t_15 = -1; __pyx_t_6 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 151, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_17 = Py_TYPE(__pyx_t_6)-&gt;tp_iternext; if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 151, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  for (;;) {
    if (likely(!__pyx_t_17)) {
      if (likely(PyList_CheckExact(__pyx_t_6))) {
        if (__pyx_t_15 &gt;= PyList_GET_SIZE(__pyx_t_6)) break;
        #if CYTHON_COMPILING_IN_CPYTHON
        __pyx_t_1 = PyList_GET_ITEM(__pyx_t_6, __pyx_t_15); __Pyx_INCREF(__pyx_t_1); __pyx_t_15++; if (unlikely(0 &lt; 0)) __PYX_ERR(0, 151, __pyx_L1_error)
        #else
        __pyx_t_1 = PySequence_ITEM(__pyx_t_6, __pyx_t_15); __pyx_t_15++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 151, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        #endif
      } else {
        if (__pyx_t_15 &gt;= PyTuple_GET_SIZE(__pyx_t_6)) break;
        #if CYTHON_COMPILING_IN_CPYTHON
        __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_6, __pyx_t_15); __Pyx_INCREF(__pyx_t_1); __pyx_t_15++; if (unlikely(0 &lt; 0)) __PYX_ERR(0, 151, __pyx_L1_error)
        #else
        __pyx_t_1 = PySequence_ITEM(__pyx_t_6, __pyx_t_15); __pyx_t_15++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 151, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        #endif
      }
    } else {
      __pyx_t_1 = __pyx_t_17(__pyx_t_6);
      if (unlikely(!__pyx_t_1)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 151, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_1);
    }
    __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) &amp;&amp; PyErr_Occurred())) __PYX_ERR(0, 151, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_i = __pyx_t_2;
/* â¦ */
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
</code></pre>

<p>The code obviously works, but, since I need to use these cycles quite often, I would like to now how to implement them correctly.</p>

<p>Which is the correct assignment for <code>lista</code> ?</p>

<p>You're best off just looping over it by index</p>

<pre><code>cdef Py_ssize_t i
cdef long val
with cython.boundscheck(False): # these two lines are optional but may increase speed
  with cython.wraparound(False):
    for i in range(lista.shape[0]):
      val = lista[i]
</code></pre>

<p>Another optimization you could probably make is to define <code>lista</code> as</p>

<pre><code>cdef long [::1] lista
</code></pre>

<p>which states that it's continuous in memory.</p>

<p>(My initial reading of the question made me think it was about the conversion from a <code>set</code>: <code>np.array(list(nx.node_connected_component(Graph, v)))</code>. I don't think this is what you're asking about, but in case it was, I can't see a way to speed up this line.)</p>

python python-2.7 optimization cython