Hi,

Robert Bradshaw wrote:
> On Nov 15, 2008, at 1:17 PM, Aaron DeVore wrote:
> 
>> I'm trying to use PyDict_Next to iterate over a dict in a way that is
>> identical to this statement:
>> for k, v in d.items():
>>     # do stuff with key and value
> 
> Yes, declare them to be PyObject* rather than object. Then you'll  
> have to do all refcounting manually (as you would have had to do  
> anyways, as PyDict_Next doesn't decref its input). However, I doubt  
> iterating over the dict manually like that will be a significant  
> speed increase than the basic Python way of doing it.

I ran timeit on this:

---------------------------------------
def items(d):
    for k,v in d.items():
        pass

def iteritems(d):
    for k,v in d.iteritems():
        pass

def dictnext(d):
    cdef Py_ssize_t pos = 0
    cdef PyObject* pk = NULL
    cdef PyObject* pv = NULL

    while PyDict_Next(d, &pos, &pk, &pv):
        k = <object>pk
        v = <object>pv
---------------------------------------

With a 1000 item dict in Py2.5, it gives me this:

    $ python2.5 -m timeit -s '...' 'items(d)'
    10000 loops, best of 3: 98.3 usec per loop
    $ python2.5 -m timeit -s '...' 'iteritems(d)'
    10000 loops, best of 3: 50.8 usec per loop
    $ python2.5 -m timeit -s '...' 'dictnext(d)'
    10000 loops, best of 3: 26.8 usec per loop

So, yes, there is a speedup. It may not be worth it for small dicts, but
the code is not so bad that it's not worth a 50% speedup for larger dicts.

Stefan
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to