とりあえずで作ったクラスを改良。

前回の記事で作ったBARRAYクラスは320x240の2階調バッファに特化した作りでした。
ビットの配列が欲しいときには有用だなと思ったのでもう少し汎用性を高めてみようと思います。

配列の長さを自由にする。

固定で9600byte(320*240/8)のbytearrayを作っていましたがこれを好きな長さのビット数で初期化出来るようにしてみます。

    buf = bytearray(9600)   

こいつを消して、かわりにinitを変更します。

    def __init__(self,len):
        if (len % 8)!= 0:
            self.buf=bytearray(int(len/8)+1)
        else:
            self.buf=bytearray(int(len/8))

8で割り切れないビット数にも対応すべく、8で割り切れない時は1byte足しています。
親切でしょ。

でもなんかもっと最適化できそう。

    def __init__(self,len):
        self.buf=bytearray(int(len/8) + int((len%8)!=0))

これでどうだ!

さて、これだけではputとgetのインデックスがいかんので直します。

    def get(self,x,y):
        idx = y * 320 + x

putにもgetにも入っている、座標からインデックスを求める奴です。
こいつを消しちゃって、代わりに引数で直接インデックスを得るようにしてみます。

    def get(self,idx):

シンプルで素敵。

無駄な部分があったのをどうにかする。

コードを作るときに処理を頭で考えながら落とし込むんですが、コードが最適化出来ていない部分なんてのが残ってるとちょいかっこ悪い。
前回つくったBARRAYにもあります、そういうところ。

        data = self.buf[idx]
        if(val):
            data |= (1 << idxb)
        else:
            data &= 0xff ^ (1 << idxb)
        self.buf[idx]=data

ここ。

一旦bufの内容をdataにコピーして加工して再度bufに入れ直してますよね。

        if(val):
            self.buf[idx] |= (1 << idxb)
        else:
            self.buf[idx] &= 0xff ^ (1 << idxb)

これでよかろうよ。
あと、ビット演算のところですか。

        if ((self.buf[idx] & (1<<idxb)) != 0 ):
            return True
        else:
            return False

これ。こうやって書き直せる。

        return bool((self.buf[idx] >> idxb) & 1)

4行が1行に。

全体のコード

とりあえずこんなところにして改良版BARRAY(BitArray)の全体を

barray.py
class BARRAY:

    # len : bit length
    def __init__(self,len):
        self.buf=bytearray(int(len/8) + int((len%8)!=0))

    # idx : bit index
    def get(self,idx):
        idxb = idx % 8
        idx = int(idx/8)
        return bool((self.buf[idx] >> idxb) & 1)

    # idx : bit index
    # val : boolean
    def put(self,idx,val):
        idxb = idx % 8
        idx = int(idx/8)
        if(val):
            self.buf[idx] |= (1 << idxb)
        else:
            self.buf[idx] &= 0xff ^ (1 << idxb)

で、動作確認。

>>> import barray
>>> ba=barray.BARRAY(10)
>>> ba.put(9,True)
>>> ba.get(9)
True
>>> ba.get(8)
False
>>> 

これの場合10bitで初期化、つまり2byteなんだけども、だからgetで15とかやっても値返ってきたりするけどそこはご愛嬌。

とりあえずこれで汎用性が高まりました!(コードもちいさくなりました!)
やったね!

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.