On 22 апр, 00:10, Ivan Illarionov <[EMAIL PROTECTED]> wrote: > On 20 ÁÐÒ, 04:10, George Sakkis <[EMAIL PROTECTED]> wrote: > > > > > On Apr 18, 9:36 pm, Ross Ridge <[EMAIL PROTECTED]> > > wrote: > > > > Ross Ridge <[EMAIL PROTECTED]> said: > > > > > If you have Python 2.5, here's a faster version: > > > > > from struct import * > > > > unpack_i32be = Struct(">l").unpack > > > > > def from3Bytes_ross2(s): > > > > return unpack_i32be(s + "\0")[0] >> 8 > > > > Bob Greschke <[EMAIL PROTECTED]> wrote: > > > > > That's not even intelligible. I wanna go back to COBOL. :) > > > > It's the same as the previous version except that it "precompiles" > > > the struct.unpack() format string. It works similar to the way Python > > > handles regular expressions. > > > I didn't know about the Struct class; pretty neat. It's amazing that > > this version without Psyco is as fast Bob's version with Psyco! Adding > > Psyco to it though makes it *slower*, not faster. So here's how I'd > > write it (if I wanted or had to stay in pure Python): > > > try: import psyco > > except ImportError: > > from struct import Struct > > unpack_i32be = Struct(">l").unpack > > def from3Bytes(s): > > return unpack_i32be(s + "\0")[0] >> 8 > > else: > > def from3Bytes(s): > > Value = (ord(s[0])<<16) + (ord(s[1])<<8) + ord(s[2]) > > if Value >= 0x800000: > > Value -= 0x1000000 > > return Value > > psyco.bind(from3Bytes) > > > HTH, > > George > > I was able to get even faster pure-python version using array module: > > a = array.array('l', ''.join(('\0' + s[i:i+3] for i in xrange(0, > len(s), 3)))) > if sys.byteorder == 'little': > a.byteswap() > > It actually moves bytes around on C level. > > test code: > import struct > import array > import sys > > unpack_i32be = struct.Struct(">l").unpack > s = ''.join(struct.pack('>i', 1234567)[1:]*1000) > > def from3bytes_ord(s): > values = [] > for i in xrange(0, len(s), 3): > Value = (ord(s[i])<<16) | (ord(s[i+1])<<8) | ord(s[i+2]) > if Value >= 0x800000: > Value -= 0x1000000 > values.append(Value) > return values > > def from3bytes_struct(s): > return [unpack_i32be(s[i:i+3] + "\0")[0] >> 8 for i in xrange(0, > len(s), 3)] > > def from3bytes_array(s): > a = array.array('l', ''.join(('\0' + s[i:i+3] for i in xrange(0, > len(s), 3)))) > if sys.byteorder == 'little': > a.byteswap() > return a.tolist() > > from timeit import Timer > > t1 = Timer("from3bytes_ord(s)", "from __main__ import s, > from3bytes_ord") > t2 = Timer("from3bytes_struct(s)", "from __main__ import s, > from3bytes_struct") > t3 = Timer("from3bytes_array(s)", "from __main__ import s, > from3bytes_array") > > print 'ord:\t', t1.timeit(1000) > print 'struct:\t', t2.timeit(1000) > print 'array:\t', t3.timeit(1000) > > Output: > ord: 7.08213110884 > struct: 3.7689164405 > array: 2.62995268952 > > Inspired by Guido's essayhttp://www.python.org/doc/essays/list2str/
And even faster: a = array.array('i', '\0' + '\0'.join((s[i:i+3] for i in xrange(0, len(s), 3)))) if sys.byteorder == 'little': a.byteswap() I think it's a fastest possible implementation in pure python -- http://mail.python.org/mailman/listinfo/python-list