The confusion you&#x27;re talking about is a Python 2 problem, not one of ambiguity.<p>Encoding and decoding are pretty well defined (though, I&#x27;ve never thought about the formal definition before). When you have an entity in its native form, it needs to be _encoded_ for the purposes of communication (in a broad sense). The encoded message can then be to be _decoded_ back to the natural form. There is no ambiguity.<p>Really, the reason people get them mixed up in Python is because Python 2 totally stacked it by adding str.encode and unicode.decode.<p>In Python 2, you can _decode_ unicode to unicode – which it does by silently _encoding_ as ascii first. This operation is total madness.<p><pre><code>    &gt;&gt;&gt; u = u&#x27;\xe9&#x27;
    &gt;&gt;&gt; u.decode(&#x27;utf8&#x27;)
    Traceback (most recent call last):
      File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
    UnicodeEncodeError: &#x27;ascii&#x27; codec can&#x27;t encode character u&#x27;\xe9&#x27; in position 0: ordinal not in range(128)
</code></pre>
The error here is in the step where you _encode_ the unicode to acsii, something you didn&#x27;t ask it to do at all.<p>And similarly, you can encode str to str (where str is really bytes in Python 2, another issue that adds to the confusion).<p>Don&#x27;t get me wrong. I feel your pain. When I was using Python 2 I also got confused about what form things were in and where I needed to encode &#x2F; decode.<p>Honestly, once I switched to Python 3, that cognitive overhead just totally vanished. str is the natural form of text, and if I need to store &#x2F; communicate it I _encode_ it to bytes (utf8, generally). When I&#x27;m loading a stored&#x2F;transmitted message, I _decode_ it to its natural text form.<p>There are edge cases that make certain situations more complex, but in terms of general usage, I feel Python 3 really got this stuff right.