それは完全に決定論的で単純です。ただし、バイトとユニコード文字列の違いに注意する必要があります。Ned Batchelder のPragmatic Unicodeを読んでください。
a
は 3 文字で構成された Unicode 文字列を参照するため、それをa
評価し、Python REPL はそれを試みます。最初のステップは、それを(文字列用の)print()
に変換することです。結果の文字列は、stdout (端末など) に関連付けられたエンコーディングに従ってバイトに変換され、これらのバイトがそこに送信されます。端末は、使用するエンコーディングに従って、受信したバイトを解釈します。str
return self
a.encode('ascii')
ASCII エンコーディングを使用して、Unicode を明示的にバイト シーケンスに変換します。その結果はバイト オブジェクトであり、その結果はprint
Python REPL によって 'd されます。繰り返しますが、最初のステップはそれを文字列に変換することです。バイトは文字列ではなく、Python 2 のエンコード/デコード エラーが証明するように、2 つの間の暗黙的な変換は非常に有害であるため、次のような結果しか得repr
られません。同等の文字列Python ソース コードのバイト リテラルに。この文字列は、以前と同じように出力されますが、違いは同じです。
では、上記と同じ結果で自分自身を>>> print(a)
呼び出します。結果はisなので、Python REPL はそれを出力しません。とについても同じです。暗黙的にではなく、明示的に印刷をトリガーし、事前に変換を行うだけです。print
print
None
>>> print(a.encode('ascii'))
>>> print(str(a.encode('ascii')))
str
確かに の逆がありstr.encode
、実際に呼び出され、オブジェクトdecode
のメソッドです。bytes
そのsome_str.encode(E).decode(E)
ため、ノーオペレーションになる可能性があります。また、途中で情報を失ったり、文字列を変更したり (未知の文字を置き換えるなど) したり、情報を失うように要求しないと例外をスローしたりすることもあります。
何らかのエンコーディングで何らかの文字列を表すバイトがある場合、それらを I/O に使用できます。実際、これは I/O を行う「ネイティブ」な方法です。すべての I/O とすべてのネットワークはバイトです。しかしprint
、文字列用です。代わりに、ファイル I/O (stdout を含む) の場合は、それらをバイナリ モードで開き、.write
メソッドを使用します。具体的にはsys.stdout
、デフォルトではテキスト モードが使用されますが、バイナリ バージョンにはsys.stdout.buffer
. もちろん、送信するバイトが異なるエンコーディングを想定して作成された場合 (またはテキストとしてまったく意図されていない場合) は、意味不明になります。