ブール値の配列のコンパクトな表現が必要です。Pythonには組み込みのビットフィールドタイプがありますか、それとも別の解決策を見つける必要がありますか?
Bitarray は、最近同様のニーズがあったときに見つけた最良の答えでした。これはCの拡張機能であり(純粋なPythonであるBitVectorよりもはるかに高速)、データを実際のビットフィールドに格納します(そのため、要素ごとにバイトを使用しているように見える、派手なブール配列よりもメモリ効率が8倍になります。)
主にビットフィールドに名前を付けて簡単に操作できるようにする場合は、たとえば、 ctypes の標準の構造およびユニオン機能を使用して、通信プロトコルで単一ビットとして表されるフラグを操作できます Pythonでctype Structure + Unionを適切に宣言しますか? - スタックオーバーフロー
たとえば、バイトの最下位4ビットを個別に処理するには、LittleEndianStructureで最下位から最上位のビットに名前を付けます。ユニオンを使用して、byteまたはintと同じデータへのアクセスを提供し、データを通信プロトコルの内外に移動できるようにします。この場合、それは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)
4ビット(ここでは、最も重要なものから印刷しましたが、印刷するとより自然に見えます)は、1、1、0、0、つまりバイナリの0xcです。
最近バージョン2.0に達した bitstring モジュールをご覧ください。バイナリデータはバイト配列としてコンパクトに格納され、簡単に作成、変更、分析できます。
バイナリ、8進数、16進数、整数(ビッグエンディアンまたはリトルエンディアン)、文字列、バイト、浮動小数点数、ファイルなどからBitString
オブジェクトを作成できます。
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')
次に、単純な関数またはスライス表記を使用してそれらを分析および変更できます。ビットマスクなどについて心配する必要はありません。
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'
ビット位置の概念もあるので、それが便利な場合は、ファイルまたはストリームのように扱うことができます。プロパティは、ビットデータの異なる解釈を与えるために使用されます。
w = g.read(10).uint
x, y, z = g.readlist('int:4, int:4, hex:32')
if g.peek(8) == '0x00':
g.pos += 10
さらに、標準のビット単位の2項演算子、パック、アンパック、エンディアンなどのサポートがあります。最新バージョンはPython 2.7および3.x用であり、純粋なPythonですが、メモリと速度の点でかなり最適化されています。
それぞれの値を2の累乗として表します。
testA = 2**0
testB = 2**1
testC = 2**3
次に、値をtrueに設定します。
table = table | testB
値をfalseに設定するには:
table = table & (~testC)
値をテストするには:
bitfield_length = 0xff
if ((table & testB & bitfield_length) != 0):
print "Field B set"
これが意味をなさない場合は、16進数表現をもう少し詳しく調べます。これは基本的に、組み込みのCアプリケーションでもブールフラグを追跡する方法です(メモリが制限されている場合)。
バイナリビット演算子!、&、|、^、>>、<<を使用しています。これらは非常にうまく機能し、基盤となるCに直接実装されます。これは通常、基盤となるハードウェアに直接あります。
BitVectorパッケージが必要な場合があります。私のpythonインストールには組み込まれていませんが、pythonサイトで簡単に追跡できます。
https://pypi.python.org/pypi/BitVector 現在のバージョン。
NumPyには、ビットフィールドを作成するために使用できる array interface モジュールがあります。
ビットフィールドが短い場合は、おそらく struct module を使用できます。それ以外の場合は、 配列モジュール のラッパーのようなものをお勧めします。
また、ctypesモジュールには bitfields が含まれていますが、私自身はこれを使用したことがありません。 警告エンプター。
Int(またはlong int)を使用してブールの配列(または整数のセット)として表す場合は、 http://sourceforge.net/projects/pybitop/files/ を参照してください。
Long intへのビットフィールドの挿入/抽出を提供します。最上位または最下位の「1」ビットを見つける。すべての1を数える;ビット反転;純粋なpythonですべて可能ですが、Cでははるかに高速です).
通信プロトコルでいくつかの制御ワード/フラグを処理する必要があり、私の焦点は、エディターがフラグ名の提案を提供し、「F3」を使用してフラグの定義にジャンプすることでした。以下のコードはこれらの要件を満たしています(残念ながら、@ nealmcbによるctypesを使用したソリューションは、今日のPyCharmインデクサーではサポートされていません)。提案は歓迎します:
""" The following bit-manipulation methods are written to take a Tuple as input, which is provided by the Bitfield class. The construct
looks weired, however the call to a setBit() looks ok and the editor (PyCharm) suggests all
possible bit names. I did not find a more elegant solution that calls the setBit()-function and needs
only one argument.
Example call:
setBit( STW1.bm01NoOff2() ) """
def setBit(TupleBitField_BitMask):
# Word = Word | bit_mask
TupleBitField_BitMask[0].Word = TupleBitField_BitMask[0].Word | TupleBitField_BitMask[1]
def isBit(TupleBitField_BitMask):
# (Word & bit_mask) != 0
return (TupleBitField_BitMask[0].Word & TupleBitField_BitMask[1]) !=0
def clrBit(TupleBitField_BitMask):
#Word = Word & (~ BitMask)
TupleBitField_BitMask[0].Word = TupleBitField_BitMask[0].Word & (~ TupleBitField_BitMask[1])
def toggleBit(TupleBitField_BitMask):
#Word = Word ^ BitMask
TupleBitField_BitMask[0].Word = TupleBitField_BitMask[0].Word ^ TupleBitField_BitMask[1]
""" Create a Bitfield type for each control Word of the application. (e.g. 16bit length).
Assign a name for each bit in order that the editor (e.g. PyCharm) suggests the names from outside.
The bits are defined as methods that return the corresponding bit mask in order that the bit masks are read-only
and will not be corrupted by chance.
The return of each "bit"-function is a Tuple (handle to bitfield, bit_mask) in order that they can be
sent as arguments to the single bit manipulation functions (see above): isBit(), setBit(), clrBit(), toggleBit()
The complete Word of the Bitfield is accessed from outside by xxx.Word.
Examples:
STW1 = STW1Type(0x1234) # instanciates and inits the bitfield STW1, STW1.Word = 0x1234
setBit(STW1.bm00() ) # set the bit with the name bm00(), e.g. bm00 = bitmask 0x0001
print("STW1.Word =", hex(STW1.Word))
"""
class STW1Type():
# assign names to the bit masks for each bit (these names will be suggested by PyCharm)
# tip: copy the application's manual description here
def __init__(self, Word):
# Word = initial value, e.g. 0x0000
self.Word = Word
# define all bits here and copy the description of each bit from the application manual. Then you can jump
# to this explanation with "F3"
# return the handle to the bitfield and the BitMask of the bit.
def bm00NoOff1_MeansON(self):
# 0001 0/1= ON (Edge)(pulses can be enabled)
# 0 = OFF1 (braking with ramp-function generator, then Pulse suppression & ready for switching on)
return self, 0x0001
def bm01NoOff2(self):
# 0002 1 = No OFF2 (enable is possible)
# 0 = OFF2 (immediate Pulse suppression and switching on inhibited)
return self, 0x0002
def bm02NoOff3(self):
# 0004 1 = No OFF3 (enable possible)
# 0 = OFF3 (braking with the OFF3 ramp p1135, then Pulse suppression and switching on inhibited)
return self, 0x0004
def bm03EnableOperation(self):
# 0008 1 = Enable operation (pulses can be enabled)
# 0 = Inhibit operation (suppress pulses)
return self, 0x0008
def bm04RampGenEnable(self):
# 0010 1 = Hochlaufgeber freigeben (the ramp-function generator can be enabled)
# 0 = Inhibit ramp-function generator (set the ramp-function generator output to zero)
return self, 0x0010
def b05RampGenContinue(self):
# 0020 1 = Continue ramp-function generator
# 0 = Freeze ramp-function generator (freeze the ramp-function generator output)
return self, 0x0020
def b06RampGenEnable(self):
# 0040 1 = Enable speed setpoint; Drehzahlsollwert freigeben
# 0 = Inhibit setpoint; Drehzahlsollwert sperren (set the ramp-function generator input to zero)
return self, 0x0040
def b07AcknowledgeFaults(self):
# 0080 0/1= 1. Acknowledge faults; 1. Quittieren Störung
return self, 0x0080
def b08Reserved(self):
# 0100 Reserved
return self, 0x0100
def b09Reserved(self):
# 0200 Reserved
return self, 0x0200
def b10ControlByPLC(self):
# 0400 1 = Control by PLC; Führung durch PLC
return self, 0x0400
def b11SetpointInversion(self):
# 0800 1 = Setpoint inversion; Sollwert Invertierung
return self, 0x0800
def b12Reserved(self):
# 1000 Reserved
return self, 0x1000
def b13MotorPotiSPRaise(self):
# 2000 1 = Motorized potentiometer setpoint raise; (Motorpotenziometer Sollwert höher)
return self, 0x2000
def b14MotorPotiSPLower(self):
# 4000 1 = Motorized potentiometer setpoint lower; (Motorpotenziometer Sollwert tiefer)
return self, 0x4000
def b15Reserved(self):
# 8000 Reserved
return self, 0x8000
""" test the constrution and methods """
STW1 = STW1Type(0xffff)
print("STW1.Word =", hex(STW1.Word))
clrBit(STW1.bm00NoOff1_MeansON())
print("STW1.Word =", hex(STW1.Word))
STW1.Word = 0x1234
print("STW1.Word =", hex(STW1.Word))
setBit( STW1.bm00NoOff1_MeansON() )
print("STW1.Word =", hex(STW1.Word))
clrBit( STW1.bm00NoOff1_MeansON() )
print("STW1.Word =", hex(STW1.Word))
toggleBit(STW1.bm03EnableOperation())
print("STW1.Word =", hex(STW1.Word))
toggleBit(STW1.bm03EnableOperation())
print("STW1.Word =", hex(STW1.Word))
print("STW1.bm00ON =", isBit(STW1.bm00NoOff1_MeansON() ) )
print("STW1.bm04 =", isBit(STW1.bm04RampGenEnable() ) )
それは印刷します:
STW1.Word = 0xffff
STW1.Word = 0xfffe
STW1.Word = 0x1234
STW1.Word = 0x1235
STW1.Word = 0x1234
STW1.Word = 0x123c
STW1.Word = 0x1234
STW1.bm00ON = False
STW1.bm04 = True
ほとんど連続したビットには、Pythonの組み込みset
とAPI互換性のある https://pypi.org/project/range_set/ モジュールがあります。名前が示すように、ビットは開始/終了ペアとして格納されます。