This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author eric.smith
Recipients eric.smith, larry
Date 2019-05-06.18:10:55
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1557166256.56.0.583302074071.issue36817@roundup.psfhosted.org>
In-reply-to
Content
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
History
Date User Action Args
2019-05-06 18:10:56eric.smithsetrecipients: + eric.smith, larry
2019-05-06 18:10:56eric.smithsetmessageid: <1557166256.56.0.583302074071.issue36817@roundup.psfhosted.org>
2019-05-06 18:10:56eric.smithlinkissue36817 messages
2019-05-06 18:10:55eric.smithcreate