Reputation: 7486
this code generates a nice loop :
for i in range(self.ix):
__pyx_t_3 = __pyx_v_self->ix;
__pyx_t_4 = __pyx_t_3;
for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) {
__pyx_v_i = __pyx_t_5;
but i want to be able to pass this iterator as argument (so i can have different iterators/generators)
if i try this :
cdef ixrange(self): return range(self.ix)
already is too unwieldy and the loop is no longer a simple loop. :
static PyObject *__pyx_f_3lib_10sparse_ary_9SparseAry_ixrange(struct __pyx_obj_3lib_10sparse_ary_SparseAry *__pyx_v_self) {
PyObject *__pyx_r = NULL;
__Pyx_RefNannyDeclarations
__Pyx_RefNannySetupContext("ixrange", 0);
__Pyx_XDECREF(__pyx_r);
__pyx_t_1 = __Pyx_PyInt_From_unsigned_int(__pyx_v_self->ix); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 139, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_1);
__pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_builtin_range, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 139, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_2);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__pyx_r = __pyx_t_2;
__pyx_t_2 = 0;
goto __pyx_L0;
/* function exit code */
__pyx_L1_error:;
__Pyx_XDECREF(__pyx_t_1);
__Pyx_XDECREF(__pyx_t_2);
__Pyx_AddTraceback("lib.sparse_ary.SparseAry.ixrange", __pyx_clineno, __pyx_lineno, __pyx_filename);
__pyx_r = 0;
__pyx_L0:;
__Pyx_XGIVEREF(__pyx_r);
__Pyx_RefNannyFinishContext();
return __pyx_r;
}
any way i can make it simple loop again ?
Upvotes: 0
Views: 125
Reputation: 30916
I don't think it is possible.
The effect of for i in range(self.ix):
is to generate a range
object, and then call next
on that range object until a StopIteration
exception is raised. That's also the behaviour that Cython takes for general for loops.
There's actually a fairly long list of conditions that have to be met for Cython to transform that into an optimized loop:
it = range(...); for i in it
won't work because you might need the range
object after the loop.range
In your case I think you're hoping for Cython to look inside the cdef
function and pick out the range. This is beyond what the current optimizer can do. But also, you can override cdef
functions in a derived class (in C++ terms, they're "virtual"), so Cython could almost never safely make the optimization.
Cython is usually able to optimize best when you really restrict the types it's working with. The request that it should generate a fast C for loop but also be able to handle arbitrary iterators does not seem realistically achievable.
Upvotes: 1