2008-09-27 2 views
39

Tôi cần một đại diện nhỏ gọn của một mảng các boolean, Python có một kiểu bitfield được xây dựng hay tôi sẽ cần phải tìm một giải pháp thay thế?Python có loại bitfield không?

+0

Đối với các trường hợp cụm từ không rõ ràng, tôi lấy nó là bạn muốn các loại đối tượng địa lý có sẵn trong các trường bit C hoặc như được mô tả ở đây? http://en.wikipedia.org/wiki/Bit_field – nealmcb

Trả lời

26

Bitarray là câu trả lời hay nhất tôi tìm thấy khi gần đây tôi có nhu cầu tương tự. Đó là một phần mở rộng C (nhanh hơn BitVector rất nhiều), lưu trữ dữ liệu của nó trong một bitfield thực tế (vì vậy nó có hiệu quả gấp tám lần bộ nhớ hiệu quả hơn một mảng boolean numpy, xuất hiện để sử dụng một byte cho mỗi phần tử.)

+0

'BitArray' có sẵn để cài đặt trên Windows không? – IAbstract

+0

Có vẻ như 'BitArray' có sẵn để cài đặt trên Linux nhưng không có gì trên trang đề xuất cài đặt PIP cho Windows. Bummer ... – IAbstract

4

NumPy có mô-đun array interface mà bạn có thể sử dụng để tạo bitfield.

+0

Mô-đun [mảng] (http://docs.python.org/library/array.html) tích hợp cũng đủ cho một mảng bit và hơn thế nữa di động (trên Python impls) hơn NumPy. – gsnedders

5

Gói BitVector có thể là những gì bạn cần. Nó không được xây dựng để cài đặt python của tôi, nhưng dễ dàng để theo dõi trên trang web python.

https://pypi.python.org/pypi/BitVector cho phiên bản hiện tại.

2

Nếu bitfield của bạn ngắn, bạn có thể sử dụng the struct module. Nếu không, tôi muốn giới thiệu một số loại bao bọc xung quanh the array module.

Ngoài ra, mô-đun ctypes chứa bitfields, nhưng tôi chưa bao giờ tự sử dụng nó. Làm trống khoang trống.

+1

Nhưng có vẻ như mô-đun struct đại diện cho mỗi bit như một char hoặc byte, do đó, nó không thực sự xử lý các trường bit như bình thường được xác định (nơi bit được đóng gói chặt chẽ với nhau trong bộ nhớ). – nealmcb

6

Tôi sử dụng toán tử bit-khôn ngoan!, &, |, ^, >> và < <. Chúng hoạt động thực sự tốt và được triển khai trực tiếp trong C cơ bản, thường trực tiếp trên phần cứng cơ bản.

6

Đại diện cho mỗi giá trị của bạn như một sức mạnh của hai:

testA = 2**0 
testB = 2**1 
testC = 2**3 

Sau đó, để đặt một giá trị đúng:

table = table | testB 

Để đặt một giá trị sai:

table = table & (~testC) 

Để thử nghiệm cho một giá trị:

bitfield_length = 0xff 
if ((table & testB & bitfield_length) != 0): 
    print "Field B set" 

Đào sâu hơn một chút vào biểu diễn hệ thập lục phân nếu điều này không có ý nghĩa với bạn. Về cơ bản, đây là cách bạn theo dõi các cờ boolean của bạn trong một ứng dụng C nhúng (nếu bạn có bộ nhớ bị giới hạn).

+0

Câu trả lời hay. Tôi thích và không thích nó là thủ công cùng một lúc. Không có một cách hợp lý hơn để tự xây dựng một lớp bitfield mặc dù. – RobotHumans

11

Bạn nên xem mô-đun bitstring, gần đây đã đạt phiên bản 2.0. Dữ liệu nhị phân được lưu trữ dưới dạng mảng byte và có thể dễ dàng được tạo, sửa đổi và phân tích.

Bạn có thể tạo đối tượng BitString từ nhị phân, bát phân, hex, số nguyên (lớn hoặc nhỏ cuối), chuỗi, byte, phao, tệp và hơn thế nữa.

a = BitString('0xed44') 
b = BitString('0b11010010') 
c = BitString(int=100, length=14) 
d = BitString('uintle:16=55, 0b110, 0o34') 
e = BitString(bytes='hello') 
f = pack('<2H, bin:3', 5, 17, '001') 

Sau đó bạn có thể phân tích và sửa đổi chúng với chức năng đơn giản hoặc ký hiệu lát - không cần phải lo lắng về mặt nạ bit, vv

a.prepend('0b110') 
if '0b11' in b: 
    c.reverse() 
g = a.join([b, d, e]) 
g.replace('0b101', '0x3400ee1') 
if g[14]: 
    del g[14:17] 
else: 
    g[55:58] = 'uint:11=33, int:9=-1' 

Ngoài ra còn có một khái niệm về một vị trí bit, do đó bạn có thể coi nó như một tệp hoặc luồng nếu điều đó có ích cho bạn. Các thuộc tính được sử dụng để cung cấp các cách giải thích khác nhau về dữ liệu bit.

w = g.read(10).uint 
x, y, z = g.readlist('int:4, int:4, hex:32') 
if g.peek(8) == '0x00': 
    g.pos += 10 

Ngoài ra còn hỗ trợ các toán tử nhị phân chuẩn, đóng gói, giải nén, kết thúc và hơn thế nữa. Phiên bản mới nhất dành cho Python 2.7 và 3.x, và mặc dù nó là Python thuần túy nhưng nó được tối ưu hóa tốt về mặt bộ nhớ và tốc độ.

+1

Tôi thích điều đó! Một chút trực quan hơn bitarray cho tôi. Cảm ơn! – weronika

+0

liên kết đã chết –

1

Nếu bạn muốn sử dụng ints (hoặc ints dài) để biểu diễn như mảng của bools (hoặc như bộ số nguyên), hãy nhìn vào http://sourceforge.net/projects/pybitop/files/

Nó cung cấp chèn/trích bitfields vào ints dài; tìm bit quan trọng nhất hoặc ít quan trọng nhất '1'; đếm tất cả số 1; bit đảo ngược; những thứ như thế có thể có trong python nguyên chất nhưng nhanh hơn nhiều ở C.

29

Nếu bạn chủ yếu muốn có thể đặt tên cho các trường bit và dễ dàng thao tác chúng, ví dụ: để làm việc với các cờ được biểu diễn dưới dạng các bit đơn trong giao thức truyền thông, khi đó bạn có thể sử dụng các tính năng Cấu trúc và Liên kết chuẩn của ctypes, như được mô tả tại How Do I Properly Declare a ctype Structure + Union in Python? - Stack Overflow

Ví dụ: để làm việc với 4 bit ít nhất một byte , chỉ cần đặt tên chúng ít nhất là quan trọng nhất trong một LittleEndianStructure. Bạn sử dụng một liên minh để cung cấp quyền truy cập vào cùng một dữ liệu dưới dạng byte hoặc int để bạn có thể di chuyển dữ liệu vào hoặc ra khỏi giao thức truyền thông. Trong trường hợp này được thực hiện thông qua các lĩnh vực flags.asbyte:

import ctypes 
c_uint8 = ctypes.c_uint8 

class Flags_bits(ctypes.LittleEndianStructure): 
    _fields_ = [ 
      ("logout", c_uint8, 1), 
      ("userswitch", c_uint8, 1), 
      ("suspend", c_uint8, 1), 
      ("idle", c_uint8, 1), 
     ] 

class Flags(ctypes.Union): 
    _fields_ = [("b", Flags_bits), 
       ("asbyte", c_uint8)] 

flags = Flags() 
flags.asbyte = 0xc 

print(flags.b.idle) 
print(flags.b.suspend) 
print(flags.b.userswitch) 
print(flags.b.logout) 

Bốn bit (mà tôi đã in ở đây bắt đầu với quan trọng nhất, mà có vẻ tự nhiên hơn khi in) là 1, 1, 0, 0, tức là 0xc trong nhị phân.