Created on 2015-01-19 19:05 by Devin Jeanpierre, last changed 2016-06-08 13:36 by python-dev. This issue is now closed.

Messages (31)

msg234324 - (view) Author: Devin Jeanpierre (Devin Jeanpierre) * Date: 2015-01-19 19:05

>>> [] = () >>> () = [] File "<stdin>", line 1 SyntaxError: can't assign to () This contradicts the assignment grammar, which would make both illegal: https://docs.python.org/3/reference/simple_stmts.html#assignment-statements

msg234325 - (view) Author: R. David Murray (r.david.murray) * Date: 2015-01-19 19:22

My guess is that it is not worth complicating the parser in order to make these two cases consistent, and it should be treated as a doc error. We'll see what other developers think.

msg234326 - (view) Author: Raymond Hettinger (rhettinger) * Date: 2015-01-19 20:12

The starting point is recognizing that this has been around for very long time and is harmless.

msg234361 - (view) Author: Kyle Buzsaki (Kyle.Buzsaki) Date: 2015-01-20 09:25

It seems that assigning to [] is the odd one out in this case. Why is this even possible? >>> [] = () >>> [] = {} >>> [] = set() >>> list() = () File "<stdin>", line 1 SyntaxError: can't assign to function call >>> () = [] File "<stdin>", line 1 SyntaxError: can't assign to () >>> {} = [] File "<stdin>", line 1 SyntaxError: can't assign to literal >>> set() = [] File "<stdin>", line 1 SyntaxError: can't assign to function call >>>

msg234364 - (view) Author: Martin Panter (martin.panter) * Date: 2015-01-20 09:40

But () is the odd one out if you consider >>> [a, b] = range(2) >>> [] = range(0) >>> (a, b) = range(2) >>> () = range(0) File "<stdin>", line 1 SyntaxError: can't assign to ()

msg234365 - (view) Author: Eryk Sun (eryksun) * Date: 2015-01-20 10:19

In ast.c, set_context checks for assignment to an empty tuple, but not an empty list. case List_kind: e->v.List.ctx = ctx; s = e->v.List.elts; break; case Tuple_kind: if (asdl_seq_LEN(e->v.Tuple.elts)) { e->v.Tuple.ctx = ctx; s = e->v.Tuple.elts; } else { expr_name = "()"; } break; https://hg.python.org/cpython/file/ab2c023a9432/Python/ast.c#l912

msg241473 - (view) Author: Nick Coghlan (ncoghlan) * Date: 2015-04-19 02:47

As Raymond notes, this is a fairly harmless quirk - it changes a SyntaxError to an iterable length dependent ValueError: >>> () = [] File "<stdin>", line 1 SyntaxError: can't assign to () >>> [] = () >>> [] = [1] Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: too many values to unpack (expected 0) I only found out about this after being puzzled when a typo in a live demo at PyCon 2015 failed to fail as I expected after seeing the presenter type a "[]" into the LHS of an assignment instead of the intended "_". Removing the data dependence to make the assignment fail immediately (even if never tested against a non-empty iterable) would involve making the handling of List_kind match that of Tuple_kind in the switch statement that eryksun quoted. I don't think it's an urgent fix, but if someone wanted to fix it (including a new test), I think it would be a reasonable contribution to accept.

msg241474 - (view) Author: Martin Panter (martin.panter) * Date: 2015-04-19 03:34

I would prefer this be fixed in the opposite direction, to allow “unpacking” an empty iterable using round brackets. I have used this syntax on purpose as a concise way to ensure that a generator is exhaused with no more yields: >>> def gen(): ... yield "partial computation" ... print("computation allowed to complete") ... >>> g = gen() >>> next(g) 'partial computation' >>> [] = g computation allowed to complete

msg241523 - (view) Author: R. David Murray (r.david.murray) * Date: 2015-04-19 17:57

There is also no reason to break currently working code, which turning this into a syntax error would od.

msg241673 - (view) Author: Mark Dickinson (mark.dickinson) * Date: 2015-04-20 18:28

> There is also no reason to break currently working code Agreed. To take one example, David Beazley's PyCon 2015 talk would have been broken by the suggested change! (See https://www.youtube.com/watch?v=MCs5OvhV9S4, at around the 42:17 mark.) If there's any code change resulting from this issue, I also think it should be to make assignment to `()` legal.

msg241790 - (view) Author: Berker Peksag (berker.peksag) * Date: 2015-04-22 09:05

I don't have a strong opinion on this, but here is a patch to make () = [] a valid assignment.

msg241792 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * Date: 2015-04-22 09:42

About the patch: I'm sure there are other tests to change, in test_syntax.py for example:: It's a syntax error to assign to the empty tuple. Why isn't it an error to assign to the empty list? It will always raise some error at runtime. >>> () = 1 Traceback (most recent call last): File "<doctest test.test_syntax[3]>", line 1 SyntaxError: can't assign to ()

msg244157 - (view) Author: Rahul Gupta (Rahul Gupta) Date: 2015-05-27 12:28

isn't it logical? [] is a mutable data structure while () is a immutable data structure (b, a) = [1, 2] is fine because a and b are mutable

msg244159 - (view) Author: Devin Jeanpierre (Devin Jeanpierre) * Date: 2015-05-27 12:42

[a, b] = (1, 2) is also fine.

msg244161 - (view) Author: Martin Panter (martin.panter) * Date: 2015-05-27 12:53

I prefer to unpack into square brackets in general because it is a mnemonic for the star argument being a list: >>> (a, *b) = range(3) >>> a 0 >>> b # A list, even though it was unpacked using tuple-like syntax [1, 2]

msg244208 - (view) Author: Raymond Hettinger (rhettinger) * Date: 2015-05-27 17:47

Berker's patch looks good. It has several virtues: * the error message is reasonable and clear * it makes the language more consistent * it doesn't break any existing code. * it makes the AST a little simpler and faster by removing a special case The patch needs to updated: * remove the whatsnew entry * fix test_codeop which expects "del ()" to raise SyntaxError * fix test_syntax which fails on "() = 1" and "del ()" * fix test_with which fails on "with mock as ()"

> isn't it logical? > > [] is a mutable data structure > while () is a immutable data structure but you don’t assign to data structures, but to names. you *modify* data structures. and in the square bracket assignment syntax you don’t modify the list created by the []. in fact the [] never even create a list. ————————————————————————————— also it’s news to me that [a, b] = range(2) works! i always did a, b = range(2), and knew that (a, b) = range(2) works. but assigning to something looking like a list literal is new and surprising to me. (and i thought i’ve mastered every corner of python’s syntax)

msg244227 - (view) Author: Nick Coghlan (ncoghlan) * Date: 2015-05-28 00:15

+1 for Martin's suggestion of removing the inconsistency the other way (i.e. allowing "() = iterable" to mean the same thing as "[] = iterable", effectively asserting that an iterable is empty) I also agree with Raymond that it doesn't need to be mentioned in the What's New doc, just in the NEWS file.

msg245308 - (view) Author: Berker Peksag (berker.peksag) * Date: 2015-06-13 09:03

Thanks for the reviews. Here is an updated patch.

msg246382 - (view) Author: Martin Panter (martin.panter) * Date: 2015-07-06 23:20

I welcome this patch to go ahead. But the documentation <https://docs.python.org/3.6/reference/simple_stmts.html#assignment-statements> also needs updating (see original post). I think it should mention that “target_list” can be empty. And it should use “iterable” instead of “sequence” in more places.

msg264223 - (view) Author: Raymond Hettinger (rhettinger) * Date: 2016-04-26 07:15

Martin, do you want to take it from here?

msg264226 - (view) Author: Berker Peksag (berker.peksag) * Date: 2016-04-26 07:40

I missed Martin's comment about the documentation. I will update my patch.

msg264249 - (view) Author: Martin Panter (martin.panter) * Date: 2016-04-26 11:23

Okay I’ll let Berker update his patch, but I’m happy to try my hand at updating the documentation if needed. I reviewed the current patch. I can’t say whether the ast.c change is good or not. But IMO the test would be better off in somewhere like /Lib/test/test_unpack.py. It is only a superficial relationship with tuples because the syntax looks the same. Also may be worth testing that [] = [] etc work as well.

msg264811 - (view) Author: Berker Peksag (berker.peksag) * Date: 2016-05-04 12:57

Here is an updated patch. I moved the test into test_unpack and added additional tests. sequence -> iterable changes should probably be applied to 3.5 as well. Thanks for the review, Martin.

msg265108 - (view) Author: Martin Panter (martin.panter) * Date: 2016-05-08 03:10

Erm, I think you went overboard with the sequence → iterable changes and subscripting; see the review. Also, I think target_list should be made optional in the grammar description.

msg265764 - (view) Author: Martin Panter (martin.panter) * Date: 2016-05-17 10:55

Hi Berker. I updated your patch according to my comments in the documentation. I hope you don’t mind. I reverted all the changes about subscripting and slicing an iterable, since this bug is only about assigning to a “target list”. Actually it is true (despite the current documentation) that you can often assign sequence[slice] = iterable But I think that is a separate problem.

msg265809 - (view) Author: Roundup Robot (python-dev) Date: 2016-05-18 05:44

New changeset 8a0754fed986 by Berker Peksag in branch 'default': Issue #23275: Allow () = iterable assignment syntax https://hg.python.org/cpython/rev/8a0754fed986

msg265811 - (view) Author: Berker Peksag (berker.peksag) * Date: 2016-05-18 05:48

Thanks Martin. Your edits look much better! :) I will be travelling for PyCon US later this week so I just committed issue23275_v4.diff with minor edits.

msg265816 - (view) Author: Roundup Robot (python-dev) Date: 2016-05-18 07:19

New changeset d3a75daf61e1 by Martin Panter in branch 'default': Issue #23275: Don’t think this made it into alpha 1 https://hg.python.org/cpython/rev/d3a75daf61e1

msg265817 - (view) Author: Martin Panter (martin.panter) * Date: 2016-05-18 07:22

I just moved the NEWS entry under the alpha 2 heading. For patches I am going to commit myself, I usually write the NEWS beforehand and remember to adjust it when committing. But perhaps I shouldn’t have done that in this case :)

msg267847 - (view) Author: Roundup Robot (python-dev) Date: 2016-06-08 13:36