[issue36817] Add = to f-strings for easier debugging.

Eric V. Smith report at bugs.python.org
Mon May 6 14:10:56 EDT 2019


New submission from Eric V. Smith <eric at trueblade.com>:

This is an alternative proposal to issue36774.

We (Eric V. Smith and Larry Hastings) propose a minor language
change.  This level of change doesn't require a PEP, so in this
post-BDFL world what we need is "a consensus among core developers".
So please vote!  Note that "+" is typed using "shift-=", and the "1"
key can be found very nearby.


Python programmers often use "printf-style" debugging.  In the
(really) bad old days this was pretty wordy:
    print "foo=", foo, "bar=", bar

f-strings make this slightly nicer to type:
    print(f"foo={foo} bar={bar}")

But you still have to repeat yourself: you have to write
out the *string* "foo", and then the *expession* "foo".
Wouldn't it be nice if you didn't have to?

f-strings are uniquely able to help with this.  Their implementation
requires them to know the original text of the expression which they
then compile.  It's not difficult for f-strings to retain the text
and prepend it; the tricky part is figuring out how to spell it.

The initial idea was to use an f-string "conversion", which we
originally spelled "!=":
    f'{foo!=}'
This spelling won't work, because f-strings permit arbitrary Python
expressions, and != of course tests for inequality.

We considered other spellings:
    !d (debug)
    !e (equals)
    !x (?)
    !! (easy to type)
We'd planned to go with !d.  In fact Eric gave a lightning talk
about this on Friday night and used this spelling.

And then!  On Saturday, the best spelling revealed itself!  Behold
the majesty of:
    {foo=}
This code:
    foo=5
    print(f"{foo=}")
would print
    foo=5

With this spelling change, we've also refined the semantics.

By default, f-strings use format() (technically they call
__format__ on the value).  But the point of this is for debugging.
But you want repr() for debugging.  When you use this on a string,
you want to see the quoted string; when you use this on a datetime
object, you want to see the datetime repr, not the default
formatted string.

Second, this is now composable with conversions.  So you can use
    {foo=!s}
to use str() instead of repr() on the value.

Relatedly, we've added a new conversion: "!f" means "use format()",
which you could never explicitly specify before.  For example, to only
format pi to two decimal places:
    f"{math.pi=!f:.2f}" => "3.14"

Finally, and this is the best part: what if you want whitespace around
the equals sign?  Well, to the left is no problem; whitespace is preserved
from the original text inside the curly braces:
    f"{ chr(65) =}" => " chr(65) ='A'"
But we also explicitly permit, and preserve, whitespace *after* the
equals sign:
    f"{chr(65) = }" => "chr(65) = 'A'"

What's particularly elegant is that we simply preserve all the
characters up to the final delimiter.  The equals sign sets a flag
but doesn't stop flushing through text.  So this:
       vvvvvvvvvv
    f"{chr(65) = }"
is *exactly* the same as this:
       vvvvvvvvvv
      "chr(65) = 'A'"

Please vote!


Eric and /arry

----------
assignee: eric.smith
components: Interpreter Core
messages: 341582
nosy: eric.smith, larry
priority: normal
severity: normal
stage: patch review
status: open
title: Add = to f-strings for easier debugging.
versions: Python 3.8

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue36817>
_______________________________________


More information about the Python-bugs-list mailing list