On 2020-09-17 12:16, Alex Hall wrote:
On Thu, Sep 17, 2020 at 8:57 PM Brendan Barnwell <brenbarn@brenbarn.net <mailto:brenbarn@brenbarn.net>> wrote:
On 2020-09-16 21:52, Dennis Sweeney wrote: > 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 "<pyshell#2>", 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 don't like this at all. It looks like assigning to a literal, which is weird.
People keep saying this, but iterable unpacking looks like assigning to a literal (a tuple or list literal) just as much.
Only if you keep using extremely simple template strings that don't contain anything except the variables you're assigning to. But this proposal allows the string to contain ANYTHING. The assignment targets may represent only a small part of it. For tuples and lists of assignment targets, the target list/tuple can't contain any extraneous material apart from the variables you're assigning to. There is no assign-to-a-tuple analogue of f"My name is {name} and I am {age} years old" = "My name is Bob and I am 100 years old"
Also PEP 622 proposes something that looks like assignment to a function call, albeit within a match/case statement.
That doesn't look like an assignment, because there's no equals sign. In any case, I'm not sure I support PEP 622 as it stands either, for similar reasons to why I don't support this current proposal.
It's natural to have symmetry between assignments and expression. For another example, look at subscripting, i.e. `__getitem__` vs `__setitem__`.
Also, it hides the assignment target within a string of potentially unbounded length and complexity, which makes it difficult to reason about code because it's hard to see when variables are being assigned to.
It's really not. A decent IDE should already be able to automatically show you assignments and usages of a variable - PyCharm does with one Ctrl+click. A syntax highlighter that can handle f-strings will make the assignments obvious at a glance.
No, it won't, unless the target string is simple. Also, the assigned values won't be easily discernible in the right-hand string, because there are no delimiters there to mark them. In any case, even if it were borderline possible with an IDE, it's still not useful or important enough to me to gum up an operation as basic as assignment. I'm fine with putting it into a function call or something like that, but not overloading the assignment statement in this way.
It also introduces a whole host of questions about the details of the parsing (i.e., how does the greediness work if the pattern is something like "{one} {two} {three} {four}" and the string to be parsed is five or ten words).
This I agree with, another reason to go for putting regexes in the f-strings like I suggested.
I think a better approach for something like this would be a .parse() method of some sort on strings, sort of like the inverse of .format(). It would parse a given string according to the format string and return a dict with the mappings (just as format can take a dict in and return the string with the substitutions made). So it would be like:
>>> pattern = "That {animal} is really {attribute}." >>> d = pattern.parse("That snake is really powerful.") >>> d['animal'] 'snake' >>> d['attribute'] 'powerful'
I think someone else just made the same proposal. But how does this solve the greediness issue?
It doesn't, but that's the least important of my objections. What it does solve is it avoids adding new behavior to the assignment statement, and it avoids creating a way to inject local variables whose names and/or values are unclear in the statement where they're created.
This wouldn't let you assign the results into local variables, but I think that's a good thing. Creating local variables "programmatically" is not a good idea; it's better to use a dict.
How is
f"{a} {b}" = "1 2"
creating local variables any more "programmatically" than
a, b = "1 2".split()
? The variables are static and visible to the compiler.
As I mentioned above, your examples are unrealistically simple. If you know your string is like "1 2" and you want to assign to a, b, you do what you just showed: use split. But in the "Bob is 100 years old" example I gave, it is more programmatic, because there is matching going on which is extracting parts of the RHS string, and you have to carefully read both the LHS and the RHS to see which parts are extracted into which variable. And that is still a pretty simple example, with relatively short and unambiguous strings on both sides of the equals sign. As the string grows longer and more complicated, it only becomes more programmatic. I think we may be arguing from different premises here, though, because I think the real issue is that for me the equals sign and local variable names are quite sacred objects. I'm not sure I would even support nested tuple and list assignments if they didn't exist and were proposed today. All of these forms of assignment that are being discussed are too complicated to put into the simple assignment statement to be used to create local variables. It's fine to have the parsing side of it going on, but there just isn't any reason, in my view, to have it be part of an assignment statement that creates local variables. Just have it be a function call that creates a dict. -- Brendan Barnwell "Do not follow where the path may lead. Go, instead, where there is no path, and leave a trail." --author unknown