[Tutor] Interactive escape sequences

eryksun eryksun at gmail.com
Tue Jan 14 14:34:13 CET 2014


On Tue, Jan 14, 2014 at 2:42 AM, Christian Alexander
<christian.h.alexander at gmail.com> wrote:
>
> Why does the interactive prompt not recognize escape sequences in strings?
> It only works correctly if I use the print function in python 3.
>
>>>> "Hello\nWorld"
> "Hello\nWorld"

Let's manually compile the following source string:

    src = r'"Hello\n"'

Here's how the input would look when typed at the prompt:

    >>> print(src)
    "Hello\n"

Compile it with the dummy filename of '<stdin>' and in 'single' mode,
as is done for the interactive prompt:

    >>> code = compile(src, '<stdin>', 'single')

Then disassemble the code object:

    >>> dis.dis(code)
      1           0 LOAD_CONST               0 ('Hello\n')
                  3 PRINT_EXPR
                  4 LOAD_CONST               1 (None)
                  7 RETURN_VALUE

The string literal is constant 0 in the code object. Constants are
stored in the code's `co_consts` tuple. Let's map `ord` to the string:

    >>> print(*[(c, ord(c)) for c in code.co_consts[0]], sep='\n')
    ('H', 72)
    ('e', 101)
    ('l', 108)
    ('l', 108)
    ('o', 111)
    ('\n', 10)

As you can see, '\n' is used to represent the linefeed control
character, which has Unicode ordinal 10 (0x0A). It's a convenient
representation that you can actually evaluate using `eval` or `exec`.
Not all object representations have this evaluation property. For
example, the representation of an io file object can't be evaluated.
But simple types usually support this ability.

Refer back to the disassembled code object. It loads the string
constant onto the stack. Then it executes the instruction PRINT_EXPR.
This instruction in turn calls `sys.displayhook`, which defaults to a
built-in function that prints the representation of the object and
stores a reference to it as `_` in the builtins namespace.

Feel free to replace the `sys.displayhook` function if you don't like
the default output. Off the top of my head, here's a function that
uses `print` instead, and stores previously printed results in a list:

    def mydisplayhook(obj):
        import builtins
        if not (hasattr(builtins, '_') and
                isinstance(builtins._, list)):
            builtins._ = []
        if obj is not None and obj is not builtins._:
            builtins._.append(obj)
        print(obj) # usr str instead of repr

    >>> import sys
    >>> sys.displayhook = mydisplayhook

    >>> "Hello\n"
    Hello

    >>> 1
    1
    >>> 2
    2
    >>> 3
    3
    >>> _
    ['Hello\n', 1, 2, 3]


More information about the Tutor mailing list