1

I noticed that running an f-string from the Python console with escape characters acts differently when not wrapped in a print() function. For example, wrapped in a print() function, \n acts as expected:

>>>a = 1
>>>b = 'frog' 
>>>c = 3

>>>print(f"""The first variable is {a}\nThe second is {b} and the third is {c}""")
The first variable is 1
The second is frog and the third is 3

Run directly, it acts differently, printing the \n as text.  

>>>f"""The first variable is {a}\nThe second is {b} and the third is {c}"""
'The first variable is 1\nThe second is frog and the third is 3'

My question is: What is the root cause of this change in behavior and is there anything one might need to be aware of when using such a formatted string in other instances - such as in queries, writing to text files, etc.?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
CNIDog
  • 374
  • 3
  • 18
  • 1
    Does this answer your question? [How to use newline '\n' in f-string to format output in Python 3.6?](https://stackoverflow.com/questions/44780357/how-to-use-newline-n-in-f-string-to-format-output-in-python-3-6) – APhillips Jan 09 '20 at 17:17
  • I found the post referenced by @APhillips and it did not answer my question, mainly because I wasn't trying to put characters inside the curly braces and I saw the `\n` character that was outside the braces was formatted perfectly in the output. I hadn't grasped the significance of the print() statement at that point. Although @John Kugelman supports Monica's referenced link does actually answer the question (hence the upvote), it did not appear in a search for a reason why the escaped character `\n` didn't render as a carriage return in the console. – CNIDog Jan 09 '20 at 20:17

2 Answers2

4

The string contains the exact same data in both cases and this happens for any string, not just f-strings. What is different is the function used to generate the display of the string.

print uses the method str.__str__() to display the string, while the interactive interpreter uses str.__repr__(). The latter function is a debug display that escapes unprintable characters.

Here are a few demonstrations. The class shows that you can override the default behavior.

>>> s = 'abc\tdef\nghi\bjkl'
>>> print(s)  # are those spaces or a tab?  Where's the i?
abc     def
ghjkl
>>> s   # makes it clear that a tab, newline and backspace are present.
'abc\tdef\nghi\x08jkl'

>>> class Test:
...  def __str__(self):
...    return '__str__'
...  def __repr__(self):
...    return '__repr__'
...
>>> t = Test()
>>> print(t)
__str__
>>> t
__repr__
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
1

This is not exclusive to f-strings. This happens with every string in python.

>>> 'a\nb'
'a\nb'
>>> print('a\nb')
a
b 

print sends your string to a stream, and it gets interpreted there. When you enter the string by itself, it will return its actual value, no additional interpretation*.

*Edit: as pointed out, it passes through __repr__.

K.Cl
  • 1,615
  • 2
  • 9
  • 18
  • There *is* addition interpretation without `print`. `__repr__` is called and the unprintable characters are escaped. The string itself doesn't contain `\n` (a two-character escape code for the newline code point). – Mark Tolonen Jan 09 '20 at 18:19
  • I see. Could you tell me why I get `"'a\\nb'"` when I use `'a\nb'.__repr__()`, but only `'a\nb'` when I use that by itself? Is it calling `__repr__` on a `__repr__`? – K.Cl Jan 09 '20 at 18:26
  • Yes, exactly. It is showing the `repr()` of the string returned by `repr()`. You can see that it starts and ends with single quote and has a literal backslash and `n` character instead of a newline. – Mark Tolonen Jan 09 '20 at 18:36