web-dev-qa-db-ja.com

Python 2.6および3のbytesvs bytearray

Python 2.6でbytesbytearrayを試しています。いくつかの違いの理由がわかりません。

bytesイテレータは文字列を返します。

for i in bytes(b"hi"):
    print(type(i))

与える:

<type 'str'>
<type 'str'>

ただし、bytearrayイテレータはintsを返します。

for i in bytearray(b"hi"):
    print(type(i))

与える:

<type 'int'>
<type 'int'>

なぜ違いがあるのですか?

Python 3.にうまく変換されるコードを書きたいのですが、Python 3でも状況は同じですか?

23
Craig McQueen

In Python 2.6バイトはstrの単なるエイリアスです。
この「疑似タイプ」は、セマンティクスと使用法が厳密に区別されているPython 3.0)と変換/互換性のあるプログラム[およびプログラマー!]を[部分的に]準備するために導入されました。 str(体系的にユニコード)およびbytes(オクテットの配列であり、データを格納しますが、テキストは格納しません)

同様に、文字列リテラルのbプレフィックスは、2.6では無効ですが、プログラム内の便利なマーカーであり、文字列をテキスト文字列ではなくデータ文字列として使用するというプログラマーの意図を明示的に示します。この情報は、プログラムがPy3kに移植されるときに、2to3コンバーターまたは同様のユーティリティで使用できます。

追加情報については、これを確認することをお勧めします SO質問

28
mjv

(少なくとも)Python 3.7

ドキュメントによると:

bytesオブジェクトは、1バイトの不変シーケンスです。

bytearrayオブジェクトは、bytesオブジェクトに対応する可変のオブジェクトです。

そして、それはbytesbytearrayに関してはほとんどそれです。実際、それらは かなり互換性があります であり、エラーをスローせずに操作に混在できるように十分に柔軟に設計されています。実際、 公式ドキュメント には、bytesAPIとbytearrayAPIの類似点を示すためのセクション全体があります。

ドキュメントからの理由に関するいくつかの手がかり:

多くの主要なバイナリプロトコルはASCIIテキストエンコーディングに基づいているため、bytesオブジェクトは、ASCII互換データを処理する場合にのみ有効で、密接に関連するいくつかのメソッドを提供します他のさまざまな方法でオブジェクトを文字列化します。

18
Harsha Goli

TL; DR

python2.6 + bytes = python2.6 + str = python3.x bytes!= python3.x str

python2.6 + bytearray = python3.x bytearray

python2.x unicode = python3.x str

長い答え

bytesstrは、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とバイトは完全に異なるものであることに注意してください)。 bytearraymutableバイトの配列であり、bytesimmutableバイトの配列です。どちらもほぼ同じ機能を持っています。 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

bytesbytearrayは、変更可能であることを除いて、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)。

4

Python 3.0で試してみました。

Python 3.0では、bytesイテレータはPython 2.6のように文字列ではなく、intsを返します。

for i in bytes(b"hi"):
    print(type(i))

与える:

<class 'int'>
<class 'int'>

bytearrayイテレータもclass 'int'sを返します。

3
Craig McQueen

どのバージョンからかはわかりませんが、bytesは実際にはstrであり、type(bytes(b"hi"))-> <type 'str'>を実行すると確認できます。

bytearrayはバイトの可変配列であり、その1つのコンストラクターは文字列を取ります。

3
van