| ▲ | kstrauser 9 days ago |
| Most excellent! I love f-strings and replaced all the various other string interpolation instances in my code with them, but they have the significant issue that you can't defer evaluating them. For instance, you can write: >>> template = 'Hello, {name}'
>>> template.format(name='Bob')
'Hello, Bob'
Until this, there wasn't a way to use f-strings formatting without interpolating the results at that moment: >>> template = f'Hello, {name}'
Traceback (most recent call last):
File "<python-input-5>", line 1, in <module>
template = f'Hello, {name}'
^^^^
NameError: name 'name' is not defined
It was annoying being able to use f-strings almost everywhere, but str.format in enough odd corners that you have to put up with it. |
|
| ▲ | ratorx 9 days ago | parent | next [-] |
| Delayed execution is basically equivalent to a function call, which is already a thing. It also has basically the same API as point of use and requires maybe 1 extra line. |
| |
|
| ▲ | paulddraper 8 days ago | parent | prev | next [-] |
| You gravely misunderstand. The point of evaluation of the expressions is the same. >>> template = t'Hello, {name}'
is still an error if you haven't defined name.BUT the result of a t-string is not a string; it is a Template which has two attributes: strings: ["Hello, ", ""]
interpolations: [name]
So you can then operate on the parts separately (HTML escape, pass to SQL driver, etc.). |
|
| ▲ | ossopite 9 days ago | parent | prev | next [-] |
| I'm not sure if t-strings help here? unless I misread the PEP, it seems like they still eagerly evaluate the interpolations. There is an observation that you can use `lambda` inside to delay evaluation of an interpolation, but I think this lambda captures any variables it uses from the context. |
| |
| ▲ | actinium226 9 days ago | parent | next [-] | | > There is an observation that you can use `lambda` inside to delay evaluation of an interpolation, but I think this lambda captures any variables it uses from the context. Actually lambda works fine here >>> name = 'Sue'
>>> template = lambda name: f'Hello {name}'
>>> template('Bob')
'Hello Bob'
| |
| ▲ | davepeck 9 days ago | parent | prev | next [-] | | > I'm not sure if t-strings help here? That's correct, they don't. Evaluation of t-string expressions is immediate, just like with f-strings. Since we have the full generality of Python at our disposal, a typical solution is to simply wrap your t-string in a function or a lambda. (An early version of the PEP had tools for deferred evaluation but these were dropped for being too complex, particularly for a first cut.) | | |
| ▲ | krick 9 days ago | parent [-] | | And that actually makes "Template Strings" a misnomer in my mind. I mean, deferred (and repeated) evaluation of a template is the thing that makes template a template. Kinda messy PEP, IMO, I'm less excited by it than I'd like to be. The goal is clear, but the whole design feels backwards. | | |
| ▲ | davepeck 9 days ago | parent [-] | | Naming is hard; for instance, JavaScript also has its own template strings, which are also eagerly evaluated. |
|
| |
| ▲ | notpushkin 9 days ago | parent | prev | next [-] | | > An early version of this PEP proposed that interpolations should be lazily evaluated. [...] This was rejected for several reasons [...] Bummer. This could have been so useful: statement_endpoint: Final = "/api/v2/accounts/{iban}/statement"
(Though str.format isn’t really that bad here either.) | | |
| ▲ | nhumrich 9 days ago | parent | next [-] | | There was a very very long discussion on this point alone, and there are a lot of weird edge cases, and led to weird syntax things. The high level idea was to defer lazy eval to a later PEP if its still needed enough. There are a lot of existing workarounds in the discussions if you are interested enough in using it, such as using lambdas and t-strings together. | |
| ▲ | LordShredda 9 days ago | parent | prev | next [-] | | Would be useful in that exact case, but would be an absolute nightmare to debug, on par with using global variables as function inputs | | |
| ▲ | notpushkin 9 days ago | parent [-] | | Yeah, to be honest, every time this comes to mind I think “wow, this would be really neat!”, then realize just using .format() explicitly is way easier to read. |
| |
| ▲ | o11c 9 days ago | parent | prev [-] | | I do think that people are far too hesitant to bind member functions sometimes: statement_endpoint: Final = "/api/v2/accounts/{iban}/statement".format
(it's likely that typecheckers suck at this like they suck at everything else though) |
| |
| ▲ | tylerhou 9 days ago | parent | prev | next [-] | | You could do something like t”Hello, {“name”}” (or wrap “name” in a class to make it slightly less hacky). | |
| ▲ | skeledrew 9 days ago | parent | prev [-] | | Lambda only captures variables which haven't been passed in as argument. |
|
|
| ▲ | davepeck 9 days ago | parent | prev | next [-] |
| PEP 750 doesn't directly address this because it's straightforward to simply wrap template creation in a function (or a lambda, if that's your style): def my_template(name: str) -> Template:
return t"Hello, {name}"
|
|
| ▲ | foobahify 9 days ago | parent | prev | next [-] |
| The issue was solved by having a rich and Turing complete language. I am not huge on adding language features. This seems like userland stuff. |
| |
| ▲ | actinium226 9 days ago | parent [-] | | I tend to agree. I think it's easy enough to use a lambda in this case >>> template = lambda name: f'Hello {name}'
>>> template('Bob')
|
|
|
| ▲ | a3w 9 days ago | parent | prev | next [-] |
| I read 'most excellent' in the Bill and Ted voice |
| |
|
| ▲ | catlover76 9 days ago | parent | prev [-] |
| [dead] |