Python3では、文字列表現として
- str型
- bytes型
の2つの型があります。
通常はstr型を使うのですが、データ通信などではbytes型を使ったりします。
両者は別モノなので、
$ python Python 3.7.1 (default, Dec 19 2018, 21:58:12) [Clang 10.0.0 (clang-1000.11.45.5)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> 'shinano gold' == 'shinano gold' True >>> b'shinano gold' == b'shinano gold' True >>> 'shinano gold' == b'shinano gold' False
となります。
そんな中、bytes型の文字列にstr型の文字列を埋め込みたいことがあったため、調べたことをメモします。
目次
- 環境
- bytes型では、f-stringsが使えない (PEP-0498より)
- bytes型では .format() が使えない (PEP-0460がobsolete)
- %演算子で変換型 %a を使う (Python 3.5〜、PEP-0461)
- bytes型にbytes型を埋め込む時は、 %演算子 + %b を使う
環境
- Python 3.7.1
bytes型では、f-stringsが使えない (PEP-0498より)
Python3.6からはf-stringsを使うことで埋め込みが楽になりましたが、bytes型には使えません。
- No binary f-strings | PEP 498 -- Literal String Interpolation | Python.org
- Is there a formatted byte string literal in Python 3.6+? - Stack Overflow
試しに実行してみると、syntaxエラーになりました。
>>> ringo = 'shinano gold' >>> fb'I love {ringo}' File "<stdin>", line 1 fb'I love {ringo}' ^ SyntaxError: invalid syntax
bytes型では .format() が使えない (PEP-0460がobsolete)
PEP-0460がobsoleteのため、bytes型には .format() がありません。
PEP 460 -- Add binary interpolation and formatting | Python.org
試しに実行してみると、AttributeErrorになりました。
>>> ringo = 'shinano gold' >>> b'I love {}'.format(ringo) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'bytes' object has no attribute 'format'
%演算子で変換型 %a を使う (Python 3.5〜、PEP-0461)
他の方法を探したところ、Python 3.5より %
演算子で %a
を使うことにより、埋め込めるようになりました。
- PEP 461 -- Adding % formatting to bytes and bytearray | Python.org
- PEP 461 - bytes および bytearray のパーセント書式化サポート | What’s New In Python 3.5 — Python 3.6.5 ドキュメント
- 4.8.4. printf 形式での bytes の書式化 | 4. 組み込み型 — Python 3.6.5 ドキュメント
試しに実行してみます。
>>> b'I love %a' % 'shinano gold' b"I love 'shinano gold'"
'
が含まれるものの、埋め込みできました。
'
が不要な場合は、replace します。
# ワンライナーの場合 >>> (b'I love %a' % 'shinano gold').replace(b"'", b"") b'I love shinano gold' # 変数を使う場合 >>> message = b'I love %a' % 'shinano gold' >>> message.replace(b"'", b"") b'I love shinano gold'
なお、 %r
も使えますが、上記の公式ドキュメントページには
'r' は 'a' の別名です。Python 2/3 の両方を対象としたコードでのみ使用すべきです。
と記載されています。
bytes型にbytes型を埋め込む時は、 %演算子 + %b を使う
>>> b'I love %b' % b'shinano gold' b'I love shinano gold'
こちらも、 %s
が使えますが、
's' は 'b' の別名です。Python 2/3 の両方を対象としたコードでのみ使用すべきです。
とのことです。