https://stackoverflow.com/questions/5471158/typeerror-str-does-not-support-the-buffer-interface の回答にあるように、文字列をバイトに変換するには2つの異なる方法があるようです。
どちらの方法がPythonicで良いのでしょうか?それとも、個人的な好みの問題でしょうか?
b = bytes(mystring, 'utf-8')
b = mystring.encode('utf-8')
bytesのドキュメントを見てみると、[
bytearray`](https://docs.python.org/3/library/functions.html#func-bytearray)が紹介されています。
bytearray([source[, encoding[, errors]])
バイトの新しい配列を返します。bytearray型は、0 <= x <256の範囲の整数の可変型配列です。Mutable Sequence Types」で説明されている、変更可能な配列の通常のメソッドのほとんどと、「Bytes and Byte Array Methods」で説明されている、バイト型が持つほとんどのメソッドを持っています。
オプションのsourceパラメータは、いくつかの異なる方法で配列の初期化に使用できます。
bytearray()は、str.encode()を使って文字列をバイトに変換します。
そして、bytearray()はstr.encode()で文字列をバイトに変換します。
__バッファインターフェイスに準拠したオブジェクトであれば、そのオブジェクトのリードオンリーバッファがバイト配列の初期化に使用されます。
__反復可能であれば、0 <= x <256の範囲の整数の反復可能でなければならず、これらは配列の初期コンテンツとして使用されます。
__引数がなければ、サイズ0の配列が作成されます。
このように、bytes
は単に文字列をエンコードするだけでなく、多くのことができます。それは、意味のある任意のタイプのソースパラメータでコンストラクタを呼び出すことができるようになるということです'Pythonic。
文字列をエンコードするには、コンストラクタを使うよりも some_string.encode(encoding)
の方がPythonicだと思います。なぜなら、最も自己文書化されているからです -- "take this string and encode it with this encoding" is clearer than bytes(some_string, encoding)
-- コンストラクタを使うときには明示的な動詞はありません。
Edit: Pythonのソースを確認しました。CPythonを使ってbytes
にunicode文字列を渡すと、encode
の実装であるPyUnicode_AsEncodedStringが呼び出されます。
また、Serdalisのコメントを参照してください -- unicode_string.encode(encoding)
は、その逆が byte_string.decode(encoding)
であるため、よりPythonicでもあり、対称性は素晴らしいものです。
思ったよりも簡単です。
my_str = "hello world"
my_str_as_bytes = str.encode(my_str)
type(my_str_as_bytes) # ensure it is byte representation
my_decoded_str = my_str_as_bytes.decode()
type(my_decoded_str) # ensure it is string representation
絶対的に最良の方法は、2つのうちのどちらでもなく、3つ目の方法です。Python 3.0以降、encode
の最初のパラメータは デフォルト* 'utf-8'
になっています。したがって、最良の方法は
b = mystring.encode()
なぜなら、デフォルトの引数の結果は、Cのコードでは文字列 "utf-8"
ではなく、NULL
であり、これはチェックするのが ずっと 速いからです。
以下に、いくつかのタイミングを示します。
In [1]: %timeit -r 10 'abc'.encode('utf-8')
The slowest run took 38.07 times longer than the fastest.
This could mean that an intermediate result is being cached.
10000000 loops, best of 10: 183 ns per loop
In [2]: %timeit -r 10 'abc'.encode()
The slowest run took 27.34 times longer than the fastest.
This could mean that an intermediate result is being cached.
10000000 loops, best of 10: 137 ns per loop
警告にもかかわらず、繰り返し実行した後のタイムは非常に安定しており、偏差はわずか2%程度でした。
Python 2 ではデフォルトの文字エンコーディングが ASCII であるため、引数なしで encode()
を使用することは Python 2 と互換性がありません。
>>> 'äöä'.encode()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)