On Sat, 28 Jan 2023 at 10:08, Rob Cliffe via Python-list <python-list@python.org> wrote: > > Whoa! Whoa! Whoa! > I appreciate the points you are making, Chris, but I am a bit taken > aback by such forceful language.
The exact same points have already been made, but not listened to. Sometimes, forceful language is required in order to get people to listen. > If it's addressed to me: How about if I wanted a program (a learning > tool) to allow the user to play with f-strings? > I.e. to type in a string, and then see what the result would be if it > had been an f-string? > I suspect there are other use cases, but I confess I can't think of one > right now. Use the REPL, which will happily evaluate f-strings in their original context, just like any other code would. You're already eval'ing, so it's exactly what you'd expect. This is not the same thing as "typing in a string", though - it's typing in code and seeing what the result would be. (Except to the extent that source code can be considered a string.) > If it's addressed to me: "it" means a function that will take a string > and evaluate it at runtime as if it were an f-string. Sure, with > caveats and limitations. And that's what I am saying is a terrible terrible idea. It will evaluate things in the wrong context, it has all the normal problems of eval, and then it introduces its own unique problems with quote characters. > And indeed Thomas Passim found this partial > solution on Stack Overflow: > def effify(non_f_str: str): > return eval(f'f"""{non_f_str}"""') You can find anything on Stack Overflow. Just because you found it there doesn't mean it's any good - even if it's been massively upvoted. > Addressing your points specifically: > 1) I believe the quote character limitation could be overcome. It > would need a fair amount of work, for which I haven't (yet) the time or > inclination. No problem. Here, solve it for this string: eval_me = ' f"""{f\'\'\'{f"{f\'{1+2}\'}"}\'\'\'}""" ' F-strings can be nested, remember. > 2) Yes in general you would have to pass it one dictionary, maybe > two. I don't see this as an insuperable obstacle. I am not sure what > you mean by "can't be done with full generality" and perhaps that's not > important. >>> def func(): ... x = 1 ... class cls: ... y = 2 ... print(f"{x=} {y=}") ... print(locals()) ... >>> func() x=1 y=2 {'__module__': '__main__', '__qualname__': 'func.<locals>.cls', 'y': 2} Maybe you don't care. Maybe you do. But locals() is not the same as "all names currently available in this scope". And, this example is definitely not something I would recommend, but good luck making this work with eval: >>> def func(): ... x = 1 ... print(f"{(x:=2)}") ... print(x) ... >>> func() 2 2 ... x = 1 ... print(eval("(x:=2)", globals(), locals())) ... print(x) ... >>> func() 2 1 > 3) Not sure I understand this. Before f-strings existed, one of the big problems with "just use str.format_map" was that you can't just pass it locals() to get all the available names. You also can't eval arbitrary code and expect to get the same results, even if you pass it globals and locals. And various other considerations here - the exact issues seen here, but flipped on their heads. So the obvious question is: why not just use str.format_map? > > Well, yes. If you asked "how can I do X", hoping the answer would be > > "with a runtime-evaluated f-string", then you're quite right - the > > answer might not be what you were hoping for. But since you asked "how > > can I evaluate a variable as if it were an f-string", the only > > possible answer is "you can't, and that's a horrible idea". > I hope that I have shown that this is a somewhat dogmatic response. And I hope that I have shown that it is fully justified. > > Don't ask how to use X to do Y. Ask how to do Y. > Good advice. Exactly. As I have shown, asking how to use f-strings to achieve this is simply not suitable, and there's no useful way to discuss other than to argue semantics. If we had a GOAL to discuss, we could find much better options. ChrisA -- https://mail.python.org/mailman/listinfo/python-list