This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: 7.2 Assignment statements documentation is vague and slightly misleading
Type: Stage:
Components: Documentation Versions:
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: docs@python Nosy List: abarnert, docs@python, martin.panter
Priority: normal Keywords:

Created on 2015-12-15 07:47 by abarnert, last changed 2022-04-11 14:58 by admin.

Messages (3)
msg256443 - (view) Author: Andrew Barnert (abarnert) * Date: 2015-12-15 07:47
From https://docs.python.org/3/reference/simple_stmts.html#assignment-statements

> If the target list contains one target prefixed with an asterisk, called a “starred” target: The object must be a sequence with at least as many items as there are targets in the target list, minus one. The first items of the sequence are assigned, from left to right, to the targets before the starred target. The final items of the sequence are assigned to the targets after the starred target. A list of the remaining items in the sequence is then assigned to the starred target (the list can be empty).
> Else: The object must be a sequence with the same number of items as there are targets in the target list, and the items are assigned, from left to right, to the corresponding targets.

The word "sequence" is used here multiple times. But the object being assigned to the target list can be any iterable (including an iterator, a set, some weird custom iterable you invent, ...).

> If the target is a target list enclosed in parentheses or in square brackets: The object must be an iterable with the same number of items as there are targets in the target list, and its items are assigned, from left to right, to the corresponding targets.

This doesn't mention that you can have a starred target inside the parenthesized or bracketed target list. More importantly, it covers the exact same case already covered above. There's semantics for "assignment of an object to a target list, optionally enclosed in parentheses or square brackets", and then semantics for "Assignment of an object to a single target... If the target is a target list enclosed in parentheses or in square brackets".

According to the grammar, a single target (no commas, parens, or brackets) is a target list, but according to the previous paragraphs it seems like it isn't.

Finally, there's nothing that explains what distinguishes between target list assignment and single target assignment. As far as I can tell, it's treated as a target list iff there's a comma, or there's square brackets around it (similar to the fact that tuples are defined by commas, but lists by square brackets--but without the exception for `()`); that should probably be documented.

There's also some needless repetition there.

I think better wording might be something like this:

> Assignment is recursively defined as follows.

> * If the target list is a comma-separated list of two or more targets, optionally enclosed in parentheses, or a comma-separated list of zero or more targets enclosed in square brackets:

(It might be worth having a note here pointing out that these are almost the same rules for non-comprehension tuple and list displays, except that () is a tuple but not a target list. Or would that just be confusing?)

(It might also be worth mentioning that this is the same feature referred to as "iterable unpacking", "sequence unpacking", and/or "tuple unpacking" in PEP 3132, the official tutorial, and lots of non-official materials?)

> ** If the target list contains one target prefixed with an asterisk, called a “starred” target: The object must be an iterable with at least as many items as there are targets in the target list, minus one. The first items of the iterable are assigned, from left to right, to the targets before the starred target. The final items of the iterable are assigned to the targets after the starred target. A list of the remaining items in the iterable is then assigned to the starred target (the list can be empty).

> ** Else: The object must be an iterable with the same number of items as there are targets in the target list, and the items are assigned, from left to right, to the corresponding targets.

> * Otherwise, the target list is treated as a single target. 

> ** If the target is an identifier (name): ...

(No section on bracketed target list here; that's already covered above.)

> ** If the target is an attribute reference: ...

> ** ...
msg256444 - (view) Author: Andrew Barnert (abarnert) * Date: 2015-12-15 07:51
As a side note, why isn't () allowed as an empty target list, like []? Then the rules for target lists vs. single targets would be exactly parallel to the rules for tuple and list displays. And the error message `can't assign to ()` seems a bit weird--you can't really assign to the tuple `a, b, c` or `(a, b, c)`, but that's not what you're doing; you're just specifying a target list.
msg256454 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015-12-15 10:44
Regarding assigning to (), see Issue 23275. Looks like there is a patch to enable it.
History
Date User Action Args
2022-04-11 14:58:24adminsetgithub: 70052
2015-12-15 10:44:55martin.pantersetnosy: + martin.panter
messages: + msg256454
2015-12-15 07:51:34abarnertsetmessages: + msg256444
2015-12-15 07:47:24abarnertcreate