Having trouble to understand the output in a Jupyter notebook ("Learning Cython")
<p>In the O'Reilly video tutorial "Learning Cython" in chapter 5, there's a notebook called <code>strings.ipynb</code>.</p>

<p>First cell loads the Cython extension:</p>

<pre><code>%load_ext cython
</code></pre>

<p>Followed by this Cython cell:</p>

<pre><code>%%cython
# cython: language_level=3

def f(char* text):
    print(text)
</code></pre>

<p>Then the following cell is used to demonstrate that a (Unicode) string cannot be used as <code>char*</code> argument:</p>

<pre><code>f('It is I, Arthur, son of Uther Pendragon')
</code></pre>

<p>The outcome here is a <code>TypeError</code> exception.</p>

<p>All of the above is what I'd expect from the author's remarks in the voice-over. However, the outcome of the next cell:</p>

<pre><code>f(b'It is I, Arthur, son of Uther Pendragon')
</code></pre>

<p>was this:</p>

<pre><code>b'It is I, Arthur, son of Uther Pendragon'
</code></pre>

<p>and that stumped me.</p>

<p>Having used a plain <code>print</code> in the function <code>f</code>, why does the output appear as if it was run through <code>repr</code> first, when inside the Cython code above it clearly was <em>not</em> run through <code>repr</code>?</p>

<p>The author doesn't even mention this somewhat (at least to me) unexpected result in the voice-over.</p>

<p>What gives? Why does the output look like it was first passed through <code>repr</code>? Are byte strings in Python 3 not "printable" (i.e. without <code>str</code> method) and therefore fall back to <code>repr</code>?</p>

<p>PS: I have to admit I'm coming from Python 2.x and haven't had too much exposure to Python 3.x, so perhaps the difference is therein.</p>

<p>Because it was. In Python 3, <code>bytes_str</code> uses <a href="https://github.com/python/cpython/blob/master/Objects/bytesobject.c#L1370" rel="nofollow"><code>bytes_repr</code> internally</a>:</p>

<pre><code>static PyObject *
bytes_str(PyObject *op)
{
    if (Py_BytesWarningFlag) {
        if (PyErr_WarnEx(PyExc_BytesWarning,
                         "str() on a bytes instance", 1))
            return NULL;
    }
    return bytes_repr(op);  // call repr on it
}
</code></pre>

<p>As such, <code>print</code> will, in essence, call <code>repr(bytes_instance)</code>.</p>

python python-3.x cython jupyter-notebook