tMC - 1 month ago 5
Python Question

# Integer to bitfield as a list

I've created a method to convert an

`int`
to a bitfield (in a list) and it works, but I'm sure there is more elegant solution- I've just been staring at it for to long.

I'm curious, how would you convert a
`int`
to a bitfield represented in a
`list`
?

``````def get(self):
results = []

results.append(1 if (self.bits &   1) else 0)
results.append(1 if (self.bits &   2) else 0)
results.append(1 if (self.bits &   4) else 0)
results.append(1 if (self.bits &   8) else 0)
results.append(1 if (self.bits &  16) else 0)
results.append(1 if (self.bits &  32) else 0)
results.append(1 if (self.bits &  64) else 0)
results.append(1 if (self.bits & 128) else 0)

return results

def set(self, pin, direction):
pin -= 1
if pin not in range(0, 8): raise ValueError

if direction: self.bits |= (2 ** pin)
else: self.bits &=~(2 ** pin)
``````

``````def bitfield(n):
return [int(digit) for digit in bin(n)[2:]] # [2:] to chop off the "0b" part
``````

This gives you

``````>>> bitfield(123)
[1, 1, 1, 1, 0, 1, 1]
>>> bitfield(255)
[1, 1, 1, 1, 1, 1, 1, 1]
>>> bitfield(1234567)
[1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1]
``````

This only works for positive integers, though.

EDIT:

Conversion to `int` using `int()` is a bit overkill here. This is a lot faster:

``````def bitfield(n):
return [1 if digit=='1' else 0 for digit in bin(n)[2:]]
``````

See the timings:

``````>>> import timeit
>>> timeit.timeit("[int(digit) for digit in bin(123)[2:]]")
7.895014818543946
>>> timeit.timeit("[123 >> i & 1 for i in range(7,-1,-1)]")
2.966295244250407
>>> timeit.timeit("[1 if digit=='1' else 0 for digit in bin(123)[2:]]")
1.7918431924733795
``````
Source (Stackoverflow)