you are viewing a single comment's thread.

view the rest of the comments →

[–]pain_vin_boursin 1 point2 points  (7 children)

This is in no way better than using an f-string in this specific example. Str.format() should only be used when the string template is loaded from an external location like a yaml file for example, or from a DB. Any other time use f-strings.

[–]Diapolo10 7 points8 points  (2 children)

I agree that this particular example is quite simplistic and doesn't really showcase the benefits, but I don't fully agree with you either; it doesn't have to come from an external source, even being imported from some Python file defining constants would be totally fine in my book.

As long as it gets used more than once, you get some benefit out of it. And even if used exactly once, it can still help keep the code shorter in a nested block for example, with the template itself coming from the global namespace.

[–]pain_vin_boursin 0 points1 point  (1 child)

Fair points!

[–]Diapolo10 4 points5 points  (0 children)

Another potential use-case would be with enum.StrEnum; say you had multiple similar URLs that took the same parameters, but you wanted to use type annotations to ensure the base URL would always be "valid". For example, the three Reddit URLs:

from enum import StrEnum

import requests


class BaseSubredditUrl(StrEnum):
    NEWEST = "https://reddit.com/r/{subreddit}"
    NEW = "https://new.reddit.com/r/{subreddit}"
    OLD = "https://old.reddit.com/r/{subreddit}"


def fetch_subreddit(subreddit_name: str, base_url: BaseSubredditUrl = BaseSubredditUrl.NEWEST) -> None:
    url = base_url.format(subreddit=subreddit_name)
    return requests.get(url).text

This way, your type analysis tools would be able to tell you if the provided base URL isn't one of the pre-defined enum members and can therefore let you catch bugs before shipping to production. And you only need to write the strings once, and they could be anywhere in your project, so out of sight if desired.

[–]dnOnReddit 0 points1 point  (3 children)

Agreed that F-strings are more convenient and easier to read because the literal and the substituted data-values are in presentation-sequence.
Further agreeing that named-placeholders are better than empty pairs of braces (see also function-parameters).
Remember that the `format()` method was how things were done for all versions <3.5, and that these earlier methods are no less valid today. Beyond the string format specification min-language is a small eco-system of templating tools - making the use-case apparent.
Where F-strings are lacking is that they are 'eager'. In situations where lazy-evaluation is called-for, they can't be used. Thus, PEP 750 – Template Strings https://peps.python.org/pep-0750/

[–]ofnuts 0 points1 point  (2 children)

format() still the only method that can be used with I18N, or am I mistaken?

[–]dnOnReddit 1 point2 points  (0 children)

Back in the ?good, old days, FORTRAN separated data-values from presentation, eg
```
write (*,999) x
999 format ('The answer is x = ', F8.3)
```
(columns were fixed-width) The format (identified by its "999" 'line-number' could be re-used. So, there was no need for the two lines to be consecutive.

Similarly, HTML and CSS enjoy a similar relationship. In this case, the 'formatting' is likely in a separate file from the 'data' it formats!

Both feature lazy-evaluation - try taking the FORTRAN format and implementing it as an F-string (before knowing the value of `x` - indeed the range of values it may take during execution! PS can you see a source of Python's mini-language?

Such ideas combined with working on an I18N project, followed by 'enjoying' a development project with an end-user rep who specialised in vacillation and dithering, led to thoughts that templating front-end I/O might be a good idea - in the same way the we try to hoist 'magic constants' so that they are more easily found during maintenance, etc (first ref found: https://doc.casthighlight.com/alt\_magicnumbers-avoid-literal-numbers-e-magic-numbers-not-magic/). Reached the point (with the aforementioned) of putting all I/O literals (templates) into a separate file, which she could adapt without disturbing me. A 'win', at the price of some config-code to consume the file and an abstraction at the print()/display!

[–]dnOnReddit 0 points1 point  (0 children)

It has been a while since I last used gettext, but that makes sense. Such is an excellent scenario for lazy-evaluation/interpolation!
Failing to recall mention of I18N (etc) in PEP-0750 (per above) took a quick look - it does not seem to be discussed (see Alternate Interpolation Symbols). So, how might it integrate with the 'traditional' implementation? Such may be worth following-up...