Re: f-strings as assignment targets
TL;DR: I propose the following behavior:
>>> s = "She turned me into a newt." >>> f"She turned me into a {animal}." = s >>> animal 'newt'
>>> f"A {animal}?" = s Traceback (most recent call last): File "
", line 1, in <module> f"A {animal}?" = s ValueError: f-string assignment target does not match 'She turned me into a newt.' >>> f"{hh:d}:{mm:d}:{ss:d}" = "11:59:59" >>> hh, mm, ss (11, 59, 59)
I do really like the idea, but assigning to a literal really makes it feel wrong... I think the best way to implement this would be through a str method that would return a dict (so that variables don't "magically" appear out of nowhere). Something like :
"She turned me into a newt.".parse("She turned me into a {animal}.")
{"animal":"newt"} This, in addition with locals().update(_), feels much better to me. Furthermore, it would allow other string-like classes, such as bytes or bytearray, to use that feature. Note that this modified version uses regular strings, not f-strings, but is that a loss ? It may even be a good thing, as f-strings are about formatting; here, it's parsing we're concerned about. We lose the invariant with = and ==, but only just. Second point, the type conversion : I think that should be left to the user on a second, separate step. There's just too many types that would need support, and we haven't even discussed user-defined types yet ! I think we should keep it simple, and stick to strings. Additionnally ,supporting !r as eval(...) looks rad to my hyped self, but it overlooks a major security risk (see all the stuff that's been discussed about pickle being unsafe). I don't think such an unsafe feature should be allowed at the core of Python. Anyway, the feature overall looks promising ! Alexis
On Fri, Sep 18, 2020 at 2:13 AM Alexis Masson
This, in addition with locals().update(_), feels much better to me. Furthermore, it would allow other string-like classes, such as bytes or bytearray, to use that feature.
But locals().update() isn't a supported operation, except in the situation where locals() is globals(). So what you're suggesting would work fine in the REPL but not in any production usage. ChrisA
So this would be a way to (1) rewrite f-strings as regexes; (2) with named
capture groups assigned to locals() instead of re.Match.groupdict()?
Would it default to `r'(.*?)'` ?
https://docs.python.org/3/library/re.html#re.Match.groupdict
https://pypi.org/project/regex/
On Thu, Sep 17, 2020, 12:54 PM Chris Angelico
On Fri, Sep 18, 2020 at 2:13 AM Alexis Masson
wrote: This, in addition with locals().update(_), feels much better to me. Furthermore, it would allow other string-like classes, such as bytes or bytearray, to use that feature.
But locals().update() isn't a supported operation, except in the situation where locals() is globals(). So what you're suggesting would work fine in the REPL but not in any production usage.
ChrisA _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/M3JEIJ... Code of Conduct: http://python.org/psf/codeofconduct/
On Fri, Sep 18, 2020 at 9:00 AM Steven D'Aprano
On Thu, Sep 17, 2020 at 06:06:39PM +0200, Alexis Masson wrote:
I do really like the idea, but assigning to a literal really makes it feel wrong...
f-strings are not literals. They are a form of eval().
Oh, that makes 'em sound way too scary :) They're more akin to a list display - a syntactic structure that yields a well-defined object, and has expressions inside it. ChrisA
On Fri, Sep 18, 2020 at 09:05:39AM +1000, Chris Angelico wrote:
f-strings are not literals. They are a form of eval().
Oh, that makes 'em sound way too scary :) They're more akin to a list display - a syntactic structure that yields a well-defined object, and has expressions inside it.
*shrug* Okay, but either way they certainly aren't a literal. Anyone who doubts that ought to disassemble an f-string and see for themselves: import dis code = compile("f'{x+1} {x-1}'", '', 'eval') dis.dis(code) -- Steve
On Fri, Sep 18, 2020 at 10:38 AM Steven D'Aprano
On Fri, Sep 18, 2020 at 09:05:39AM +1000, Chris Angelico wrote:
f-strings are not literals. They are a form of eval().
Oh, that makes 'em sound way too scary :) They're more akin to a list display - a syntactic structure that yields a well-defined object, and has expressions inside it.
*shrug*
Okay, but either way they certainly aren't a literal. Anyone who doubts that ought to disassemble an f-string and see for themselves:
import dis code = compile("f'{x+1} {x-1}'", '', 'eval') dis.dis(code)
Agreed. The advantage of them being a syntactic structure (rather than some sort of masked eval() call) is that the proposal at hand DOES make sense. Consider: # List display (or tuple w/o the brackets) x = [spam, ham] # Unpacking assignment (ditto) [spam, ham] = x # Formatted string txt = f"foo bar {qty:d} quux" # Proposed string unpacking f"foo bar {qty:d} quux" = txt It doesn't make sense to assign to a function call. It does make sense to assign to a construct that is handled by the parser. We have assignment forms that look just like lookups ("x = a[1]" and "a[1] = x"). But yes, all of this is also predicated on f-strings NOT being literals. ChrisA
participants (4)
-
Alexis Masson
-
Chris Angelico
-
Steven D'Aprano
-
Wes Turner