Pythonのbytearray()関数を徹底解説!可変なバイナリデータの扱い方
Pythonでバイナリデータを扱う際、生のバイト列を操作する必要があることはbytes()関数の記事でも解説しました。しかし、一度作成したバイト列の内容を変更したいという場面も出てきます。例えば、データの受信中に逐次追記したり、特定の位置のバイトを書き換えたりする場合などです。このような「変更可能なバイト列」を扱うためにPythonが提供しているのが**bytearray()関数**です。この記事では、bytearray()関数の基本的な使い方から、bytes()との違い、そして具体的な活用事例までを初心者にもわかりやすく解説します。
目次
bytearray()関数とは?Pythonにおける可変なバイト列の生成
Pythonのbytearray()関数は、変更可能な(ミュータブルな)バイト列オブジェクトを生成するための組み込み関数です。bytes型が一度生成されると内容を変更できない「イミュータブル(不変)」であるのに対し、bytearray型は、リストのように要素の追加、削除、変更が可能です。
bytesとbytearrayの決定的な違い
この2つの型の最大の違いは、変更可能かどうかという点です。
| 特徴 | bytes (バイト列) | bytearray (バイト配列) |
| 変更可能性 | 不変(イミュータブル) | 可変(ミュータブル) |
| 用途 | 固定されたバイナリデータ | 変更・加工が必要なバイナリデータ |
| パフォーマンス | 読み込みが速い | 書き込みや変更に適している |
bytearray()関数の基本的な使い方
bytearray()関数の使い方は、bytes()関数と非常に似ています。
1. 空のバイト配列の生成
引数を指定しない場合、空のバイト配列を生成します。
empty_bytearray = bytearray()
print(empty_bytearray) # 出力: bytearray(b'')
print(type(empty_bytearray)) # 出力: <class 'bytearray'>
2. サイズを指定してヌルバイトで初期化
整数を1つ引数に指定すると、その数だけ\x00(ヌルバイト)で埋められたバイト配列を生成します。
ten_null_bytearray = bytearray(10)
print(ten_null_bytearray) # 出力: bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
print(len(ten_null_bytearray)) # 出力: 10
3. イテラブル(リストやタプルなど)から生成
0から255までの整数を含むイテラブルを引数に指定すると、その数値に対応するバイト配列を生成します。
# リストからバイト配列を生成
byte_list = [72, 101, 108, 108, 111] # H, e, l, l, o のASCIIコード
hello_bytearray = bytearray(byte_list)
print(hello_bytearray) # 出力: bytearray(b'Hello')
4. 文字列からエンコーディングを指定して生成
文字列をバイト配列に変換する際、文字列とエンコーディングを引数で渡します。
# UTF-8でエンコードしてバイト配列を生成
s_utf8 = "こんにちは"
encoded_bytearray_utf8 = bytearray(s_utf8, 'utf-8')
print(encoded_bytearray_utf8) # 出力: bytearray(b'\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf')
これも、文字列オブジェクトの.encode()メソッドの結果をbytearray()に渡すのと同様です。
# .encode()メソッドの結果をbytearray()に渡す
s = "Python"
encoded_bytes = s.encode('utf-8')
mutable_from_bytes = bytearray(encoded_bytes)
print(mutable_from_bytes) # 出力: bytearray(b'Python')
bytearrayオブジェクトの操作(変更)
bytearrayの最大の特徴は、作成後にその内容を変更できる点です。リスト操作と非常によく似ています。
要素の変更
インデックスを使って、個々のバイト値を変更できます。
data = bytearray(b"Hello")
print(data) # 出力: bytearray(b'Hello')
data[0] = 74 # H (72) を J (74) に変更
print(data) # 出力: bytearray(b'Jello')
data[4] = 33 # o (111) を ! (33) に変更
print(data) # 出力: bytearray(b'Jell!')
要素の追加・削除
.append()でバイトを追加したり、delで削除したりできます。
data = bytearray(b"abc")
print(data) # 出力: bytearray(b'abc')
data.append(100) # d (100) を追加
print(data) # 出力: bytearray(b'abcd')
del data[0] # 最初の要素を削除
print(data) # 出力: bytearray(b'bcd')
スライス代入
スライスを使って、バイト列の一部をまとめて置き換えることも可能です。
data = bytearray(b"PythonProgramming")
print(data) # 出力: bytearray(b'PythonProgramming')
data[6:13] = b"Script" # "Program" の部分を "Script" に置き換え
print(data) # 出力: bytearray(b'PythonScripting')
bytearray()関数の活用事例
1. リアルタイムデータ処理・ストリーム処理
ネットワークからリアルタイムでデータを受信し、それを逐次処理していくようなストリーム処理において、bytearrayは非常に有効です。受信したデータをbytearrayにappendしていき、特定の区切り文字やデータ長に達したら処理するといったことが容易になります。
2. バイナリファイルの編集
既存のバイナリファイルの一部を読み込み、変更を加えてから書き戻すような処理にbytearrayが適しています。例えば、画像ファイルのメタデータ部分を書き換えたり、ゲームのセーブデータを編集したりする際に利用できます。
# バイナリファイルの特定部分を書き換える例 (簡略化)
# dummy_data.binを 'wb' モードで作成 (存在しない場合)
# with open('dummy_data.bin', 'wb') as f:
# f.write(b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09')
with open("dummy_data.bin", "rb+") as f: # r+b (読み書きモード、バイナリ)
# ファイル全体をbytearrayとして読み込む
file_content = bytearray(f.read())
print(f"元の内容: {file_content}")
# 特定のバイトを書き換え (例: 3番目のバイトを0xAAに)
if len(file_content) > 2:
file_content[2] = 0xAA
# ファイルの先頭に戻り、変更した内容を書き込む
f.seek(0)
f.write(file_content)
f.truncate() # 元のファイルより短くなった場合、余分な部分を切り捨てる
# 再度読み込んで確認
with open("dummy_data.bin", "rb") as f:
modified_content = f.read()
print(f"変更後の内容: {modified_content}")
# 出力例:
# 元の内容: bytearray(b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09')
# 変更後の内容: b'\x00\x01\xaa\x03\x04\x05\x06\x07\x08\x09'
3. バイト列としてのバッファ
特定のプロトコルやデバイスとの通信で、固定長または可変長のバイトバッファを効率的に管理する必要がある場合、bytearrayが利用されます。
bytearray()関数と関連する関数・型
bytes()
先述の通り、bytes()は不変なバイト列を生成します。一度データを確定したら変更の必要がない場合はbytesを使用するのが一般的です。
memoryview()
memoryview()は、bytesやbytearrayといった既存のバイナリデータに対する「ビュー」を作成します。これにより、元のデータをコピーすることなく、効率的にデータの特定部分にアクセスしたり、変更したりすることが可能になります(bytearrayのmemoryviewは変更可能)。
.decode()と.encode()
bytearrayもbytesと同様に、.decode()メソッドで文字列にデコードしたり、文字列を.encode()して得られたbytesオブジェクトをbytearray()に渡してバイト配列に変換したりできます。
# bytearrayを文字列にデコード
my_bytearray = bytearray(b"Hello World")
decoded_string = my_bytearray.decode('utf-8')
print(decoded_string) # 出力: Hello World
まとめ
Pythonのbytearray()関数は、変更可能なバイト列を扱うための強力なツールです。bytes型が不変であるのに対し、bytearray型はデータの追加、削除、変更が自由に行えるため、リアルタイムデータ処理やバイナリファイルの編集など、動的なバイナリデータ操作が必要な場面で真価を発揮します。
bytearray()関数は、変更可能なバイト列を生成します。bytes型(不変)とは対照的に、要素の追加、削除、変更が可能です。bytes()と同様に、サイズ指定、イテラブル、文字列(エンコーディング指定)から生成できます。ファイルI/Oのバイナリモード、リアルタイムデータ処理、バイナリファイルの編集などに活用されます。
.decode()で文字列へ、文字列を.encode()してからbytearray()でバイト配列へ変換できます。
この関数をマスターすることで、Pythonでのバイナリデータ処理の幅が大きく広がるでしょう。
■「らくらくPython塾」が切り開く「呪文コーディング」とは?
■プロンプトだけでオリジナルアプリを開発・公開してみた!!
■AI時代の第一歩!「AI駆動開発コース」はじめました!
テックジム東京本校で先行開始。
■テックジム東京本校
「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。
<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。
<月1開催>放送作家による映像ディレクター養成講座
<オンライン無料>ゼロから始めるPython爆速講座



