pythonメニュー

bytes型とstr型,python2と3の比較


文字列 str と bytes型

bから始まる'〜'の表現は、bytes型というバイト列です。
似ていますが、strとbytesの連結は出来ません。 文字列 str と bytes型の比較例です。 次のように、どちらかのの型に変換すれば比較できます。

>>> a="ABC"
>>> b=b"ABC"
>>> a == b
False
>>> a.encode('utf-8') == b
True
>>> a == b.decode('utf-8')
True
>>>

文字列と16byte整数をbytesにまとめて、それを復元

'M'の文字1つと 226の2byteデータを、まとめて3byteのバイナリに変換し、それを復元する例です。
bin="M".encode('utf-8') + int(266).to_bytes(2, 'big')
print( bin, type(bin) )
print( chr(bin[0]) , int.from_bytes(bin[1:3], byteorder='big'))
b'M\x01\n' <class 'bytes'>
M 266

Python3


strからbytes →'あい'.encode('utf-8') #この結果『b'\xe3\x81\x82\xe3\x81\x84'』 
例えば、'wb'のオープンの場合、f.writeの引数で文字列を引数するとエラーになる。そこで、バイナリに変換して出力する例
with open( FILE_PATH, 'wb' ) as f:
   f.write('aabあいbcc'.encode('utf-8'))


UTF-8 bytesからstr →b'\xe3\x81\x82\xe3\x81\x84'.decode('utf-8') #この結果『'あい'』 
'wb'のオープンの場合、文字列をそのまま出力できる。
with open( FILE_PATH, 'w' ) as f:
   f.write('aabあいbcc')


b'\xe3\x81\x82\xe3\x81\x84'は
バイト列(bytes)と呼ばれる。
Python 3 では、"..." や '...' Unicode文字列(unicode)と同義となった。
あえてバイト列として扱いたい文字列を表現したい場合の "..." や '...' の前に b または B を記述して、
バイト列(bytes)であることを示します。
(Python 2 では b や B は無視されます。)



「%」は剰余演算子以外で、文字列に対して用いるフォーマット演算子としての機能があります。

>>> "--- %d ---" % 123
'--- 123 ---'
>>> "--- %s %d. ---" % ("value is ",123)
'--- value is  123. ---'
>>>

ですが、文字列を埋め込む場合は、formatメソッドを使う方が分かりやすいでしょう。
total=506
print("合計は{}です。".format(total))

文字列リテラルの前にfまたはFを置く「f文字列(f-strings)」という表現も存在します。
print(f"合計は{total}です。")

Python 3.x で削除

Python 2.x の
EasyDialogs モジュールには、Macintosh で単純なダイアログ操作を行うためのルーチンが入っています。
このモジュールは Python 3.x で削除されました。

配列やNumpy と bytes型 との変換

bytes.join(iterable)やbytearray.join(iterable)の機能です。
iterable 中のバイナリデータを結合した bytes または bytearray オブジェクトを返します。
(joinはクラスメソッドでなく、オブジェクトのメソッドです。)
Numpy配列からbinaryデータ(bytes型)への変換方法を示します。
b''.join( np.array([127,255,0x800]) )	#b'\x7f\x00\x00\x00\xff\x00\x00\x00\x00\x08\x00\x00'

a=np.array([127,255], dtype="int8")
b''.join( a )			#b'\x7f\xff'

a=np.array([127,255,0x800], dtype="int16")
b''.join( a )			#b'\x7f\x00\xff\x00\x00\x08'

a=np.array([127,255,0x800], dtype="int32")
b''.join( a )			#b'\x7f\x00\x00\x00\xff\x00\x00\x00\x00\x08\x00\x00'
なお、Numpy オブジェクトには、tobytes()メソッドがあり、これで上記と同じことができます。
a=np.array([127,255,0x800], dtype="int16")
a.tobytes()			#b'\x7f\x00\xff\x00\x00\x08'

上記の逆です。
binaryデータ(bytes型)からNumpy配列へ、そして配列への変換方法を示します。
lst=np.frombuffer(b'\x7f\x00\xff\x00\x00\x08', dtype="int16")  #2バイト、リトルエンディアンで変換

lst		#array([ 127,  255, 2048], dtype=int16)

lst.tolist()	#[ 127,  255, 2048]
なお、上記のようにnp.frombufferで得たnumpy.ndarrayは、イミュータブル(書き換え禁止, read-only)になっています。
よって、lst*=2 のように、変更しようとすると、「assignment destination is read-only」のエラーになります。(誤って値を更新してしまうのを防ぐのに便利)
この情報は、次のようにflagsで確認できます。(numpy.ndarrayのメモリレイアウトの情報はflagsに格納されている。)
>>> lst.flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : False
  WRITEABLE : False
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False
>>>
そして、「lst.flags.writeable=True」と変更することができ、これで書き換え可能になります。
しかし、次のメッセージが出て、この変更自体ができな場合があります。
「cannot set WRITEABLE flag to True of this array」
元の配列が書き換え禁止の場合、ビューのWRITEABLE属性をTrueに変更して書き換え禁止を解除することができない規則があり、 つまり、このエラーは書き換えできない配列のビューを操作した場合のメッセージです。
(ビューとは、スライスで得た配列などです。 例 a_view = a[0:] )
回避方法はa.copy()の情報で変更します

逆に元の配列が書き換え可能である場合は、ビューの変数で書き換え禁止にしても元の配列から要素の値が更新できます。