Python f-string cheat sheets (2022)

(fstring.help)

97 points | by shlomo_z 8 hours ago ago

18 comments

  • nickcw 5 hours ago ago

    From the f-strings PEP 498

    https://peps.python.org/pep-0498/

    > This PEP is driven by the desire to have a simpler way to format strings in Python.

    I think f-strings have become the thing they were trying to replace and they are now more complicated than the old % interpolation.

    I still like f-strings and use them a lot but if you look at the cheat sheet, they are no longer simple.

    • ayhanfuat 5 hours ago ago

      > if you look at the cheat sheet, they are no longer simple.

      Most of the formatting options in the cheat sheet have always been available with f-strings. They are part of the Format Specification Mini Language (https://docs.python.org/3/library/string.html#format-specifi...) and both string.format and f-strings use the same spec. f-strings have some additional capabilities like inline expressions and debugging/logging with `=`.

      • disgruntledphd2 an hour ago ago

        The equals addition is basically the best thing ever, I almost always use it for logging. Incredibly helpful (for me, at least).

    • lynnharry 2 hours ago ago

      I don't think "simple" here means lack of functions. It means more intuitive and simpler code, and easier curve of learning. And to me f-string is very simple.

  • roenxi 4 hours ago ago

    This looks like a cheatsheet for writing a hard-to-read Python script. I don't know who gets karmic brownie points for a f"{string:>20}" field, but under most normal cases it'd be better to use rjust() directly and not force people to remember Yet Another DSL.

    Once a reader could be reasonably expected to consult reference material while working out what a print() is doing something has gone wrong. This is the programmer equivalent of wearing too much makeup.

    • cloudbonsai 3 hours ago ago

      You haven't seen the full depth yet. Suppose that you encountered with this line:

          print(f"{n:.2g}")
      
      What will it print? Here is the official explanation from https://docs.python.org/3.12/library/string.html#formatspec:

          g - General format. For a given precision p >= 1, this rounds the number to p significant digits and then formats the result in either fixed-point format or in scientific notation, depending on its magnitude. A precision of 0 is treated as equivalent to a precision of 1.
      
          The precise rules are as follows: suppose that the result formatted with presentation type 'e' and precision p-1 would have exponent exp. Then, if m <= exp < p, where m is -4 for floats and -6 for Decimals, the number is formatted with presentation type 'f' and precision p-1-exp. Otherwise, the number is formatted with presentation type 'e' and precision p-1. In both cases insignificant trailing zeros are removed from the significand, and the decimal point is also removed if there are no remaining digits following it, unless the '#' option is used.
      
          With no precision given, uses a precision of 6 significant digits for float. For Decimal, the coefficient of the result is formed from the coefficient digits of the value; scientific notation is used for values smaller than 1e-6 in absolute value and values where the place value of the least significant digit is larger than 1, and fixed-point notation is used otherwise.
      
          Positive and negative infinity, positive and negative zero, and nans, are formatted as inf, -inf, 0, -0 and nan respectively, regardless of the precision.
      
      Make sense? You now should be able to see why it's called f-string.
      • jgtrosh 3 hours ago ago

        Yes, it's a generalisation of `%g` in f-string's ancestor printf(3). This is what people expect to find in formatting templates.

  • jokoon 29 minutes ago ago

    I use them and I discovered a few that I did not know

  • ilovetux 2 hours ago ago

    I love python f-strings. I dont use the format specifiers that this article points out.

    Also, even though use in log messages is discouraged, I go ahead and use them. It will let me know if there is some code path where the proper variable is never set. This usually comes out through testing, especially during fuzzing so I guess it really only works because of my testing, otherwise it would come up during runtime...

  • lenkite 2 hours ago ago

    Say if you were designing a new language and wanted to include string formatting as a feature. Would you personally choose Python f-strings or C-style format strings or Rust-style formats ?

    • hmry an hour ago ago

      In terms of format string syntax, Rust is extremely similar to Python (and C++'s new std::format is also similar). So in that sense it seems Python-style "{name:fmt}" has won. Though the others don't support arbitrary expressions inside of the string.

      On the other hand, you have formatting as an expression that evaluates to a string like f"..." in Python, vs formatting as a set of functions that take the same input format but do various things like printf/snprintf/write!/format!/std::print/std::format... Here it seems Python's approach had too many drawbacks, considering they just added formatted templates t"..." that don't evaluate to a string.

      If I were to design a new language, I would use a Python-like "{expr:fmt}" syntax for formatting, but I would make it evaluate to some sort of FormatTemplate object that code can inspect.

    • pansa2 an hour ago ago

      Can you get away with just f-strings? Python also has `string.format` for situations where the string needs to be built dynamically.

      Are there languages which only have an f-string-like feature without a `string.format` equivalent?

  • asicsp 5 hours ago ago

    See also this quiz: https://fstrings.wtf/

  • xavdid 7 hours ago ago

    Ah, these are great! f-strings are so powerful, but I can never remember the arcane little syntax. Definitely bookmarking this.

  • blueflow 3 hours ago ago

    I fail to see the purpose of f-strings if they end up as complex as printf formatting. Maybe use printf at this point?

    • ForceBru 2 hours ago ago

      I think the purpose is to put variables directly in the string literal instead of calling `printf`. Looking at an f-string immediately tells you where each value will be located in the output. `printf` requires you to read the format string, then look at the arguments, then count where a particular value will be printed.

      • lou1306 28 minutes ago ago

        `printf`/`str.format` are also prone to nasty failures: if you forget a variable (e.g., `str.format("{} {} {}", 0, 1)`), you only find out when you crash with an IndexError at runtime.

    • Hamuko 2 hours ago ago

      You don't really need to use any of these. Really the most useful one is f"{var=}" for us print() debuggers. But f"{var:#x}" is the same as f"{hex(var)}", so feel free to pick whatever you prefer.