Python 2.6でbytes
とbytearray
を試しています。いくつかの違いの理由がわかりません。
bytes
イテレータは文字列を返します。
for i in bytes(b"hi"):
print(type(i))
与える:
<type 'str'>
<type 'str'>
ただし、bytearray
イテレータはint
sを返します。
for i in bytearray(b"hi"):
print(type(i))
与える:
<type 'int'>
<type 'int'>
なぜ違いがあるのですか?
Python 3.にうまく変換されるコードを書きたいのですが、Python 3でも状況は同じですか?
In Python 2.6バイトはstrの単なるエイリアスです。
この「疑似タイプ」は、セマンティクスと使用法が厳密に区別されているPython 3.0)と変換/互換性のあるプログラム[およびプログラマー!]を[部分的に]準備するために導入されました。 str(体系的にユニコード)およびbytes(オクテットの配列であり、データを格納しますが、テキストは格納しません)
同様に、文字列リテラルのbプレフィックスは、2.6では無効ですが、プログラム内の便利なマーカーであり、文字列をテキスト文字列ではなくデータ文字列として使用するというプログラマーの意図を明示的に示します。この情報は、プログラムがPy3kに移植されるときに、2to3コンバーターまたは同様のユーティリティで使用できます。
追加情報については、これを確認することをお勧めします SO質問 。
(少なくとも)Python 3.7
bytes
オブジェクトは、1バイトの不変シーケンスです。
bytearray
オブジェクトは、bytesオブジェクトに対応する可変のオブジェクトです。
そして、それはbytes
対bytearray
に関してはほとんどそれです。実際、それらは かなり互換性があります であり、エラーをスローせずに操作に混在できるように十分に柔軟に設計されています。実際、 公式ドキュメント には、bytes
APIとbytearray
APIの類似点を示すためのセクション全体があります。
ドキュメントからの理由に関するいくつかの手がかり:
多くの主要なバイナリプロトコルはASCIIテキストエンコーディングに基づいているため、bytesオブジェクトは、ASCII互換データを処理する場合にのみ有効で、密接に関連するいくつかのメソッドを提供します他のさまざまな方法でオブジェクトを文字列化します。
TL; DR
python2.6 +
bytes
= python2.6 +str
= python3.xbytes
!= python3.xstr
python2.6 +
bytearray
= python3.xbytearray
python2.x
unicode
= python3.xstr
長い答え
bytes
とstr
は、python 3.x以降、pythonで意味が変更されました。
最初に質問にすぐに答える、python 2.6 bytes(b"hi")
は、不変のバイト配列(8ビットまたはオクテット)。したがって、各byte
のタイプは単純にbyte
であり、python 2.6+のstr
と同じです(ただし、python 3.xの場合はそうではありません)。
bytearray(b"hi")
もバイトの可変配列です。しかし、そのタイプを尋ねると、それはint
です。これは、pythonがbytearray
の各要素を0〜255の範囲の整数(8ビット整数のすべての可能な値)として表すためです。ただし、bytes
配列の要素は、そのバイトのASCII値として表されます。
たとえば、Python 2.6 +で考えてみましょう。
>>> barr=bytearray(b'hi')
>>> bs=bytes(b'hi')
>>> barr[0] # python shows you an int value for the 8 bits 0110 1000
104
>>> bs[0] # python shows you an ASCII value for the 8 bits 0110 1000
'h'
>>> chr(barr[0]) # chr converts 104 to its corresponding ASCII value
'h'
>>> bs[0]==chr(barr[0]) # python compares ASCII value of 1st byte of bs and ASCII value of integer represented by first byte of barr
True
python 3.xはまったく別の話です。ご想像のとおり、python2.6 +でstr
リテラルがbyte
を意味するのは奇妙なことです。まあ この答えはそれを説明しています
Python 3.xでは、str
はUnicodeテキストです(以前は単なるバイトの配列でした。Unicodeとバイトは完全に異なるものであることに注意してください)。 bytearray
はmutableバイトの配列であり、bytes
はimmutableバイトの配列です。どちらもほぼ同じ機能を持っています。 python 3.xで上記の同じコードを再度実行すると、結果は次のようになります。 Python 3.x
>>> barr=bytearray(b'hi')
>>> bs=bytes(b'hi')
>>> barr[0]
104
>>> bs[0]
104
>>> bs[0]==barr[0] # bytes and bytearray are same thing in python 3.x
True
bytes
とbytearray
は、変更可能であることを除いて、python 3.xと同じものです。
あなたが尋ねるかもしれないstr
はどうなりましたか? python 3のstr
はpython 2のunicode
に変換され、unicode
タイプは冗長であるため、python 3から削除されました。
Python 3にうまく変換されるコードを書きたいのですが、Python 3でも状況は同じですか?
それはあなたが何をしようとしているのかによります。バイトを扱っていますか、それともバイトのASCII表現を扱っていますか?
バイトを扱っている場合、私のアドバイスはPython 2でbytearray
を使用することです。これはpython 3でも同じです。しかし不変性が失われます。 、それがあなたにとって重要な場合。
ASCIIまたはテキストを処理している場合は、Python 2で文字列をu'hi'
として表します。これは、pythonでも同じ意味です。 <python>] 3. 'u'
はPython 2で特別な意味を持ち、python 2に文字列リテラルをunicode
タイプとして扱うように指示します。 python 3の「u」は意味がありません。Python 3のすべての文字列リテラルはデフォルトでUnicodeです(python 3ではstr
タイプ、python 3ではunicode
タイプと混同されます。 python>] 2)。
Python 3.0で試してみました。
Python 3.0では、bytes
イテレータはPython 2.6のように文字列ではなく、int
sを返します。
for i in bytes(b"hi"):
print(type(i))
与える:
<class 'int'>
<class 'int'>
bytearray
イテレータもclass 'int'
sを返します。
どのバージョンからかはわかりませんが、bytes
は実際にはstr
であり、type(bytes(b"hi"))
-> <type 'str'>
を実行すると確認できます。
bytearray
はバイトの可変配列であり、その1つのコンストラクターは文字列を取ります。