On 2008-04-21 14:50:13 -0600, Ivan Illarionov <[EMAIL PROTECTED]> said:
> On 22 апр, 00:10, Ivan Illarionov <[EMAIL PROTECTED]> wrote: >> On 20 ÁÐÒ, 04:10, George Sakkis <[EMAIL PROTECTED]> w > rote: >> >> >> >>> 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 Geeze! :) How did struct get so fast? I'm guessing there have been improvements since 2.3 (which is what I've been working on). I'm going to be able to go back to my IBM PC XT pretty soon. :) Thanks! -- http://mail.python.org/mailman/listinfo/python-list