r/Python • u/assumptionkrebs1990 • 5d ago
Meta Consistency of new unpacking syntax in 3.15?
Not sure if this question belongs here or if the flair is right, but I have a question.
You can now (3.15 and up, PEP 448) unpack nested lists and dictionaries with * and ** in comprehension expressions, for example:
>>> ranges = [range(i) for i in range(5)]
>>> [*item for item in ranges]
[0, 0, 1, 0, 1, 2, 0, 1, 2, 3](Code from PEP)
but I also try to do small checks and this doesn't seem possible:
>>> [b for b in [*a if min(a)<2 else *(a[::-1]) for a in [(1, 2), (3, 4)]] if b%2==0]
File "<python-input-4>", line 1
[b for b in [*a if min(a)<2 else *(a[::-1]) for a in [(1, 2), (3, 4)]] if b%2==0]
^
SyntaxError: cannot unpack only part of a conditional expressionI need junky work around:
[c for c in [*b for b in [a if min(a)<2 else (a[::-1]) for a in [(1, 2, 3), (4, 5, 6)]]] if c%2==0]
[2, 6, 4]And also having an outside list due to the fact that there is no option to filter the elements the stars unpacks. Any chances this improves with future versions?
Update: thanks for the responses everyone, I think u/latkde explains it very well in their post. Yes in practice I think I can't use this kind of syntax for a while now and be it just get compatibility with older versions, it would be just for my own side projects and quick checks answering math questions online. I was just curios because needing to put an expression in parentheses is not something I am very used to in Python (and try to avoid if I can) and since the previous versions seemed to have relaxed the rules in this regard (or was it just help, exit and quit?) I didn't understand why the expression above wouldn't work.
12
u/latkde Tuple unpacking gone wrong 5d ago
The unpacking is part of the generator syntax. Unpacking does not create a new value category, so it cannot be used within conditionals.
Formally, we are in an “flexible expression” context. Unpacking (a starred expression) can only occur in a flexible expression. The elements of an expression list (such as the contents of a
[…]literal can be expressions, as can be the value expression in a… for … in …generator expression. So you can say*some_expression for … in …, but not*some_expression if … else *other_expression– the conditional expression syntax doesn't allow flexible expressions there.That means we can say
[*(… if … else …) for … in …]but not[*… if … else *… for … in …].