In-place array modification

Jeff Epler jepler at unpythonic.net
Mon Jul 19 10:44:10 EDT 2004


With 2.4's generator expressions and slice assignment, you should be
able to perform these kinds of operations in-place.  You would write
something like
    s[:] = (d[si] for si in s)
.. unfortunately, this doesn't work.
TypeError: can only assign array (not "generator") to array slice

I thought that numarray arrays might accept generators, but I get an odd
error there too:
>>> n = numarray.zeros((5,))
>>> n[:] = iter(range(5))
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
libnumarray.error: Type object lookup returned NULL for type -1

If you can identify a small set of operations that need to be in-place
(like this simple base-to-base mapping), you could code them in C or
Pyrex---as a bonus, they'll be fast, too.  The map() variant is not likely
to be very fast (in fact, I'd be surprised if it was faster than the
inplace for-loop version).  string.translate() would work in this case,
very quickly, but create an extra copy just like the map() solution would.

>>> s = map(d.get, s)
might beat
>>> s = map(lambda c: d[c], s)
but probably not by enough to matter.

Here's a run with my implementation of "itranslate" in Pyrex:
>>> from array import array
>>> s = array('c', "ATAGCTGCT")
>>> t = string.maketrans('ATCG', 'TAGC')
>>> itranslate.itranslate(s, t)
>>> s
array('c', 'TATCGACGA')

And here's the Pyrex source for itranslate:

cdef extern from "Python.h":
    int PyObject_AsWriteBuffer(object, void **, int *) except -1
    int PyString_AsStringAndSize(object, char **, int *) except -1

def itranslate(object obuf, object ot):
    cdef int blen, tlen, i
    cdef unsigned char *buf, *t

    PyObject_AsWriteBuffer(obuf, <void **>&buf, &blen)
    PyString_AsStringAndSize(ot, <char **>&t, &tlen)

    if tlen != 256:
        raise ValueError, "Translation must be length-256 string"

    for i from 0 <= i < blen:
        buf[i] = t[buf[i]]

On my 650MHz x86 machine, a translation of a 1 megabyte buffer with
itranslate takes 15ms according to "timeit" (that's 66 megs per second,
which doesn't seem that great, but probably beats the plain Python code
handily)

Jeff
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-list/attachments/20040719/cf06ce9d/attachment.sig>


More information about the Python-list mailing list