Live data from Hacker News

Python 3's F-Strings: An Improved String Formatting Syntax

realpython.com

81–90 of 147 posts

Re: Python 3's F-Strings: An Improved String Formatting Syntax

#81
post #70

A wart is the standard logging module, which uses %-style strings. For example: log.debug("Unexpected, got %r", (got,)) By doing it this way, it can defer rendering the string until it is actually needed, which is (assumed to be) a win when the logging module is normally just going to toss the low level messages away rather than emit them anywhere. I think you lose this optimization if you use f-strings. I don't thin…

Even if logging can't use f-strings, is there a reason it can't use `string.format`?

Limiting logging to `%`-formatting seems to be an inconsistency similar to supporting `%` but not `format` on `bytes` and `bytearray`.

Re: Python 3's F-Strings: An Improved String Formatting Syntax

#82
post #14
post #2

I can't say I like the f" syntax much. I think JS's backtick is better. Other than that, I agree, much better than % and less verbose than .format. It's just the f" or f' that doesn't sit right with me

I think you are right to prefer JS's backtick notation, but not in your reason. The main problem with python's f" syntax is that it's just a very complex, non-extensible hack whereas in javascript you can prefix a tag to specify how the interpolation happens. Instead of this, f-strings have a lot of hardcoded and often broken behavior which can't be fixed let alone customized. For example, you can specify a field wid…

> Instead of this, f-strings have a lot of hardcoded and often broken behavior which can't be fixed let alone customized

They are customizable on an object-to-be-formatted basis (__format__ special method).

Re: Python 3's F-Strings: An Improved String Formatting Syntax

#83
post #76
post #70

A wart is the standard logging module, which uses %-style strings. For example: log.debug("Unexpected, got %r", (got,)) By doing it this way, it can defer rendering the string until it is actually needed, which is (assumed to be) a win when the logging module is normally just going to toss the low level messages away rather than emit them anywhere. I think you lose this optimization if you use f-strings. I don't thin…

Also, remember that the first argument to the logging functions is considered to be a format string. So using f-strings is not just less efficient, it is also not robust, unless you do: logging.debug("%s", f"Unexpected, got {got}") because otherwise, if the format string is the first/only argument, and `got` unexpectedly contain `%`, an exception will be raised due to a missing format parameter. (Also, for the loggin…

I dont think this is true. I just tried with the following program and it runs as expected (Run on Python 3.7.9).

    import logging
    got = "%d"
    logging.warning(f"hi {got}")
    logging.debug(f"hi {got}")
Output

    WARNING:root:hi %d
    DEBUG:root:hi %d

Re: Python 3's F-Strings: An Improved String Formatting Syntax

#84

From reading the comments in the discussion here, I'm curious why the f-string syntax is so all-over-the-place? - f"{foo}" uses the default format - f"{foo!r}" uses repr to format - f"{foo=}" uses a special-cased debugging introspection - f"{foo:formatstr}" uses the default format with a custom format string - f"{foo:{bar}}" uses a dynamic format string It seems like `!r` and `=` should have been implemented with `:r…

Yeah, there seem to be a number of special cases.

The rules for the trailing `=` case are particularly complicated:

    {x=} -> "x="+repr(x)
    {x=:.2f} -> "x="+format(x, ".2f")
    {x=:} -> "x="+format(x, "")
    {x=:!s:20} -> "x="+format(str(x), "20")
    {x=:!r:20} -> "x="+format(repr(x), "20")
https://bugs.python.org/msg341732

Re: Python 3's F-Strings: An Improved String Formatting Syntax

#85
post #76
post #70

A wart is the standard logging module, which uses %-style strings. For example: log.debug("Unexpected, got %r", (got,)) By doing it this way, it can defer rendering the string until it is actually needed, which is (assumed to be) a win when the logging module is normally just going to toss the low level messages away rather than emit them anywhere. I think you lose this optimization if you use f-strings. I don't thin…

Also, remember that the first argument to the logging functions is considered to be a format string. So using f-strings is not just less efficient, it is also not robust, unless you do: logging.debug("%s", f"Unexpected, got {got}") because otherwise, if the format string is the first/only argument, and `got` unexpectedly contain `%`, an exception will be raised due to a missing format parameter. (Also, for the loggin…

As the sibling comment points out, it actually doesn't work that way. The first parameter is only treated as a format string _if_ there are arguments. If not, it is treated as a literal string: https://github.com/python/cpython/blob/dcea78ff53d02733ac598...

Re: Python 3's F-Strings: An Improved String Formatting Syntax

#86

From reading the comments in the discussion here, I'm curious why the f-string syntax is so all-over-the-place? - f"{foo}" uses the default format - f"{foo!r}" uses repr to format - f"{foo=}" uses a special-cased debugging introspection - f"{foo:formatstr}" uses the default format with a custom format string - f"{foo:{bar}}" uses a dynamic format string It seems like `!r` and `=` should have been implemented with `:r…

What if your format string started with "r" or "=", or was simply just one of those characters?

Re: Python 3's F-Strings: An Improved String Formatting Syntax

#87

From reading the comments in the discussion here, I'm curious why the f-string syntax is so all-over-the-place? - f"{foo}" uses the default format - f"{foo!r}" uses repr to format - f"{foo=}" uses a special-cased debugging introspection - f"{foo:formatstr}" uses the default format with a custom format string - f"{foo:{bar}}" uses a dynamic format string It seems like `!r` and `=` should have been implemented with `:r…

!r is one of a class of conversion flags, others are !a which uses ascii(), !s which uses str().

“=” in the format-spec (the thing that comes after the “:”) is the numeric padding alignment specifier (other alignment specifiers are left “”, and center “^”.)

Re: Python 3's F-Strings: An Improved String Formatting Syntax

#88
Some experiences of counterparts from languages I've used, although it's like bike shedding but it's still user experience. It would be user-hostile if not carefully designed:

Ruby: Good but there are too many kinds of syntax. Use double quote to interpolate which need to escape a lot. And single quote doesn't interpolate, which makes many code bases very mixed and merging code is annoying. I wonder if they swapped them in the first place would it make the mixed thing better because it's easier to settle on single quote?

C#: Support multiline, still awkward because it uses double quote.

JavaScript: Simple, intuitive yet extensible. It's pretty useful because in JavaScript world embedded languages are very common (CSS, HTML etc). And I find ${} is slightly better than {} in C# and Scala because of the escaping. The community is pretty much settled with single quote, and only use back tick when interpolating so it suck less than Ruby.

Scala: Extensible. Very thoughtful and cool, you can indent and strip margin. It's a little bit cumbersome to write multiline when it's space sensitive in JavaScript

Elixir: Extremely extensible, the Sigil is not only for strings but also for other syntax.

Clojure: It's weird that I put Clojure here, yet I find (str "Hello" name "!") is not far from dedicated interpolation syntax. S-expr, simplicity and all that.

I would say Clojure's is good enough for me, but JavaScript is pretty awesome already - maybe it would be perfect if it can strip margin as well.

Re: Python 3's F-Strings: An Improved String Formatting Syntax

#89
The issue with f-strings is that they can't be used for i18n. AFAIK, it is impossible to make `_(f"Hello, {name}")` work - at least without a preprocessor or very arcane bytecode manipulation magic. This is unlike much uglier but common and well-supported `_("Hello, %(name)s") % {"name": name}`.

In the examples I've used `_` as an alias for a `gettext` call - I believe this is a common practice to do something like `from django.utils.translation import ugettext as _`.

Re: Python 3's F-Strings: An Improved String Formatting Syntax

#90
post #14

Earlier quoted context omitted.

I think you are right to prefer JS's backtick notation, but not in your reason. The main problem with python's f" syntax is that it's just a very complex, non-extensible hack whereas in javascript you can prefix a tag to specify how the interpolation happens. Instead of this, f-strings have a lot of hardcoded and often broken behavior which can't be fixed let alone customized. For example, you can specify a field wid…

Yes. Python in general has gone from being “executable pseudo code” to a series of complex language design trade offs largely because it had failed to grasp the right abstractions in its evolution. Backtick functions in JS are so powerfully clever and basically impossible to recreate in Python.

> Python in general has gone from being “executable pseudo code” to a series of complex language design trade offs

Agree with this 100%.

> because it had failed to grasp the right abstractions in its evolution.

I'd be interested to know what you think the language's designers should have done differently?

Post reply on HN