ok, so this is a bit complex, I'm writing a bit-field function using a template, which can consist of:

field( Template, Value )

field( [1,7,15]        ,255 ) #int representation...
field( ['1','3','4']   ,255 ) #bit representation...
#>>> [1,7,15]

field( [1,7,15]        ,[1,7,15] )
field( ['1','3','4']   ,[1,7,15] )
#>>> 255

so what I'm looking for is a way to R-shift Value by the binary size of the data field during enumeration in a generator...

here's the unfinished int >>> list method for example:

return [(Value>> ? )&(~(~0<<int(t)) if t.__class__==str else t) for t in Template]

what would I have to do to the ? to get what I'm after??

thanks :)

a way to R-shift Value by the binary size of the data field

I don't understand what you want to do. What is the binary size of the data field ? Can you give examples of input values and expected output values ?

GAH! curse my horrible explainations... lol

what I mean is, [1,7,15] evaluates to [ 0b1, 0b111, 0b1111 ] in which the size of these is specified by ['1','3','4']

so what I need to do is, in the for loop, for each run:

1: (Value>> 0 )&(~(~0<<int(t)) if t.class==str else t)
2: (Value>> 1 )&(~(~0<<int(t)) if t.class==str else t)
3: (Value>> 8 )&(~(~0<<int(t)) if t.class==str else t)

what can I do to incrimint the value-shift like I want??
enumerate() obviousely won't work, unless I use it to gather the sizes from the template and sum() them up... heh :P
isn't there a better way??

Now I don't understand how the 1 3 4 become 0 1 8. Can you explain the connection between the two ?


p   = 0
p+1 = 1
p+3 = 4

was looking at 7 instead of 3 and not realizing when I wrote the post, so that's how I got 8

quick solution (probably not the best)

sums = [int(v) if v.__class__==str else len(bin(v))-2 for v in Template]
return [(Value>> (sum(sums[:i]) if i else 0) )&(~(~0<<int(t)) if t.__class__==str else t) for i,t in enumerate(Template)]

EDIT: scratch that, it's not working right... heh

EDIT2: fixed

and vice-versa, though again, probably not the best:

def field(template, value):
    template, value = list(reversed(template)), list(reversed(value))
    sums = [int(v) if v.__class__==str else len(bin(v))-2 for v in template]
    v = {'':0}; [v.update({'':( v['']<<sums[i])|f }) for i,f in enumerate(value)]; return v['']


>>> field([0b1,0b111,0b1111], [0,3,9])

Here is my solution

def field(template, value):
    res = 0
    for t, v in zip(template, value)[::-1]:
        if t.__class__ is int:
            t = t.bit_length()
            t = int(t)
        res = (res << t)|v
    return res

if __name__ == '__main__':
    res = field([0b1,0b111,0b1111], [0,3,9])
    print(res, bin(res))
commented: very nice +4

oh yea, I forgot about zip()
that's much better than what I'm currently doing :D

btw NICE reversal method =D
god, I've been using list(reversed( )) for so long... =3=

and .bit_length()
why is this not documented anywhere 9_9
many thanks :)

btw, your for loop, fitting my coding preferences: ;)

for t, v in zip(template, value)[::-1]: res = (res << (t.bit_length() if t.__class__ is int else int(t)) )|v

now if only I could do ; for lol

bit_length() is documented in python 3. It has been backported to 2.7.

Edit: it is actually also documented in 2.7.

Edit: in python 2, t.__class__ in (int, long) would be better, although a little slower than t.__class__ is int.

if it's just 2 types, this is better ;)

>>> def f(v): print True if v is int or long else False

>>> f(int())
>>> f(long())

truthfully, I'm not entirely sure if it's faster than tuple creation, though logic tells me it should be.
figured that one out a while back, had issues with more than 2 types back when I was triangulating primitives.


Edit: it is actually also documented in 2.7.

huh... in the times I've looked at the docs, I've never seen it.
though I don't look much at those docs anymore...
they're confusing and don't tell you much of what you need to know... heh
I'm literally better off asking for a better example in most cases.

Qt has better documentation, and even their docs suck :P

Unfortunately v is int or long means

(v is int) or long

It is always True because bool(long) is True. If you want to test if a value is an int or a long, the valid ways are

isinstance(v, (int, long)) # good programming
type(v) in (int, long) # doesn't work with subtypes
v.__class__ in (int, long) # dirty but faster
commented: oh ok, my mistake :) +4