Python: bytes 型 と str 型の違い。変換方法

Python 3 では、文字列データを表すのに bytes と str がある。bytes のインスタンスは符号なし 8 ビット値で構成され、ASCII(文字コードの標準規格) エンコーディングで表示される。str は Unicode コードポイントの文字列を含む。
エンジニア速報は Twitter の@commteで配信しています。
bytes 型 と str 型 のポイント
- str と bytes は同時に扱えない
- ファイルにバイナリデータを書き込む場合、バイナリモードでオープンしなければならない
- bytes は 8 ビットの値の列を含む
- str は Unicode コードポイントの文字列を含む
バイナリデータについて
データ形式を大別すると、テキストとバイナリに分類される。バイナリデータとは、文字・画像・音楽・動画などテキストデータ以外のデータ。人が見ても意味が不明瞭なデータである。
バイナリデータを操作するためのものは 2 つある。
- bytes:イミュータブル(変更不可)。バイトのタプルのようなもの
- bytearray:ミュータブル(変更可)。バイトのリストのようなもの
組み込み型 — Python 3.10.0b2 ドキュメント
bytes 型
bytes 型はコンピューターにとって扱いやすいバイト配列を扱う。バイトの不変なシーケンス(複数の要素を順番に並べたデータ型)である。str 型は人が読み書きしやすいが、bytes 型はコンピューターにとって扱いやすい。ハードディスクに直接保存可能である。
b の後で、クォートで囲むとバイト型になる。次のコードでは、encode() を使い文字列をエンコードしている。ord()は Unicode コードポイントの数値文字を返し、chr() はそれを文字列に変換する。2 進数は bin()、hex()は 16 進数。
Unicode コードポイントを取得する場合、python3 はユニコード文字列なので、u を付けなくてよい。
# 文字列をエンコードする
print("あ".encode())
# b'\xe3\x81\x82'
a = b'\xe3\x81\x82'
print(list(a))
# [227, 129, 130]
b = [227, 129, 130]
print(bytes(b))
# b'\xe3\x81\x82'
print(bytearray(b))
# bytearray(b'\xe3\x81\x82')
# Unicode コードポイントを表す数値文字を返す
print(ord("あ"))
# 12354
# Unicode コードポイント 数値文字を文字列に変換
print(chr(12354))
# あ
# 2進数で返す
print(bin(ord("あ")))
# 0b11000001000010
# 16進数で返す
print(hex(ord("あ")))
# 0x3042
bytes リテラルでは ASCII 文字のみが許可されている。ASCII コードとは、文字を表現する 2 進数のことだが、リンク先の ASCII コード表が使われる。
参考:ASCII コード表
bytearray 型
bytearray オブジェクトはミュータブルなので変更可能である。
b = [227, 129, 130]
print(bytearray(b))
# bytearray(b'\xe3\x81\x82')
ba = bytearray(b)
ba[1] = 127
print(ba)
# bytearray(b'\xe3\x7f\x82')
str と bytes は同時に扱えない
str 型同士、bytes 型同士は連結可能だが、str 型と bytes 型を演算子(>, +, ==, %
)を用いて連結することはできない。比較も不可。
a = "あ".encode()
b = "い".encode()
print(a + b)
# b'\xe3\x81\x82\xe3\x81\x84'
print("あ" + b)
# TypeError: can only concatenate str (not "bytes") to str
str は str でのみ連結可能だとエラーが表示される。
バイナリデータをファイルに書き込むとエラーになる
ファイルをテキスト書き込みモード(w)で開くとエラーになる。
with open('sample.bin', 'w') as f:
f.write(b'\xe3\x81\x82')
# TypeError: write() argument must be str, not bytes
ファイルをバイナリ書き込みモードを使うとエラーは起きない。
with open('sample.bin', 'wb') as f:
f.write(b'\xe3\x81\x82')
str インスタンスはバイナリエンコーディングを持たず、bytes インスタンスはテキストエンコーディングを持たない。
encode() と decode()
.encode()関数を使うと文字列をバイト型にエンコードすることができる。UTF-8 による符号化では、漢字や仮名などの表現に 3 バイトを要する。(UTF-8 - Wikipedia)
c = 'あ'
print(type(c))
print(c)
# UTF-8 を指定してエンコード
e = c.encode('utf-8')
print(type(e))
# <class 'bytes'>
print(e) # バイト列を表示
# b'\xe3\x81\x82'
# エンコーディングを指定してデコード
print(e.decode('utf-8'))
# あ
次は、encode()と decode()関数を使って、文字型を確認する関数。
常に str に変換する
次のコードは常に str を返す関数。
オブジェクトの型を調べる isinstance() を用いて、第一引数に渡したオブジェクト b が第二引数に渡した bytes に属していれば、decode()の処理を行う。repr() は文字列で返す関数である。
e = 'あ'
# ひらがな「あ」をエンコードする
print(e.encode('utf-8'))
# b'\xe3\x81\x82'
def to_str(b):
if isinstance(b, bytes):
v = b.decode('utf-8')
else:
v = b
return v
# 「あ」のエンコード文字を渡す
print(repr(to_str(b'\xe3\x81\x82')))
# 'あ'
print(repr(to_str('あ')))
# 'あ'
常に bytes に変換する
こちらは、常に bytes を返す関数。
def to_bytes(s):
if isinstance(s, str):
v = s.encode('utf-8')
else:
v = s
return v
print(repr(to_bytes('あ')))
# b'\xe3\x81\x82'
print(repr(to_bytes(b'\xe3\x81\x82')))
# # b'\xe3\x81\x82'
Python おすすめ本
スポンサード リンク
関連記事
- Python : 再帰は大きな問題が小さな問題に収束するように使う
- Python: f-string(f 文字列)と「:」の便利な使い方
- Python: MySQL へ接続するモジュール mysqlclient(MySQLdb)の使い方
- Python: インポートしたときに「ModuleNotFoundError」になる場合の対処法
- Python: カウンタ。Counter()関数で要素数を計算する
- Python: Requests-HTML の使い方
- Python: BeautifulSoup 使い方(タイトル・HTML 取得など)
- Python: Requests モジュールの使い方(スクレイピング、データ収集など)
- Python: SQL の基本コマンドと sqlite3 モジュール
- Python: JSON とは何か?(loads、dumps など)
Leave a Comment