Welcome, guest | Sign In | My Account | Store | Cart

List like protocol for bit field manipulation

Python, 37 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#
# bitfield manipulation
#

class bf(object):
    def __init__(self,value=0):
        self._d = value

    def __getitem__(self, index):
        return (self._d >> index) & 1 

    def __setitem__(self,index,value):
        value    = (value&1L)<<index
        mask     = (1L)<<index
        self._d  = (self._d & ~mask) | value

    def __getslice__(self, start, end):
        mask = 2L**(end - start) -1
        return (self._d >> start) & mask

    def __setslice__(self, start, end, value):
        mask = 2L**(end - start) -1
        value = (value & mask) << start
        mask = mask << start
        self._d = (self._d & ~mask) | value
        return (self._d >> start) & mask

    def __int__(self):
        return self._d

k = bf()
k[3:7]=5
print k[3]
print k[5]
k[7]=1
print k[4:8]
print int(k)

This class allow you to access the individuals bits of a number with a protocol similar to list indexing and slicing.

Since the class doesn't provide a __len__ method, calls like: k[-1] of k[2:] wont work.

5 comments

Patrick Edsall 13 years, 3 months ago  # | flag

error in this code:

    mask = 2L**(end - start) -1

should be

    mask = 2L**(end - start + 1) -1
dan 13 years, 2 months ago  # | flag

Actually modifying the code that way breaks the python list conventions; asking for k[4:8] should give the 4th, 5th, 6th and 7th elements, but not the 8th.

Patrick Martin 10 years, 3 months ago  # | flag

I get an error:

line 19, in __getslice__
    return (self._d >> start) & mask
TypeError: unsupported operand type(s) for >>: 'str' and 'int'

Is there something I am missing here?

Trevor Joynson 8 years, 6 months ago  # | flag

@Patrick, I'm a bit late (only a year and 9 months!), but your problem is you are using a string for your value.

Richard Foulkes 7 years, 3 months ago  # | flag

Got alarm when using bin()

-> TypeError: 'bf' object cannot be interpreted as an index

Had to add alias index call at end of class.

__index__ = __int__

Not sure about the difference between index and int methods should be. Might not be the best solution, but worked for my testing.

Since bin() was added in 2.6 and this post has been around for nearly 12 years, I thinks its held up well.

Thanks for the help!

Created by Sébastien Keim on Tue, 12 Feb 2002 (PSF)
Python recipes (4591)
Sébastien Keim's recipes (24)

Required Modules

  • (none specified)

Other Information and Tasks