newbie question: any better way to write this code?

Peter Otten __peter__ at web.de
Wed Dec 27 11:05:59 EST 2006


neoedmund wrote:

> i want to let a byte array to be xor with some value.
> but code show below i wrote seems not so .. good..., any better way to
> write such function? thanks.

> [code]
> def xor(buf):
>         bout=[]
>         for i in range(len(buf)):
>                 x = ord(buf[i])
>                 x ^= 123
>                 bout.append(chr(x))
>         return "".join(buf)

'bout' not 'buf', I think.

A simple improvement: loop over the characters:

def xor2(buf):
#...
    for c in buf:
        x = ord(c)
#...  

If you want to xor always with the same value you can prepare a lookup map
once for every possible input value:

_map = dict((chr(i), chr(i ^ 123)) for i in range(256))
def xor3(buf, _map=_map):
    return "".join(_map[c] for c in buf)

However, you still have to loop over the characters of buf in Python. Here's
a way to move that loop (in the generator expression) into the
str.translate() method which is coded in C:

_map = "".join(chr(i^123) for i in range(256))
def xor4(buf):
    return buf.translate(_map)

Now let's do some measurements:

$ python2.5 -m timeit -s"from xor import xor; s = 'alpha ' * 10" "xor(s)"
10000 loops, best of 3: 87.9 usec per loop
$ python2.5 -m timeit -s"from xor import xor2; s = 'alpha ' * 10" "xor2(s)"
10000 loops, best of 3: 78.4 usec per loop
$ python2.5 -m timeit -s"from xor import xor3; s = 'alpha ' * 10" "xor3(s)"
10000 loops, best of 3: 38.5 usec per loop
$ python2.5 -m timeit -s"from xor import xor4; s = 'alpha ' * 10" "xor4(s)"
1000000 loops, best of 3: 1.15 usec per loop

But what if you don't know the value to xor with in advance?

def xor5(buf, n=123):
    map = "".join(chr(i^123) for i in range(256))
    return buf.translate(map)

$ python2.5 -m timeit -s"from xor import xor5; s = 'alpha ' * 10" "xor5(s)"
1000 loops, best of 3: 221 usec per loop

There goes our speed-up. I can think of various ways to remedy that, but if
your input strings are long you might not even care:

$ python2.5 -m timeit -s"from xor import xor2; s = 'alpha ' * 1000" "xor
(s)"
100 loops, best of 3: 7.93 msec per loop
$ python2.5 -m timeit -s"from xor import xor5; s = 'alpha ' * 1000" "xor
(s)"
1000 loops, best of 3: 242 usec per loop

Peter



More information about the Python-list mailing list