Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it valid to assign to an empty list but not to an empty tuple?

This came up in a recent PyCon talk.

The statement

[] = [] 

does nothing meaningful, but it does not throw an exception either. I have the feeling this must be due to unpacking rules. You can do tuple unpacking with lists too, e.g.,

[a, b] = [1, 2] 

does what you would expect. As logical consequence, this also should work, when the number of elements to unpack is 0, which would explain why assigning to an empty list is valid. This theory is further supported by what happens when you try to assign a non-empty list to an empty list:

>>> [] = [1] Traceback (most recent call last):   File "<stdin>", line 1, in <module> ValueError: too many values to unpack 

I would be happy with this explanation, if the same would also be true for tuples. If we can unpack to a list with 0 elements, we should also be able to unpack to a tuple with 0 elements, no? However:

>>> () = ()   File "<stdin>", line 1 SyntaxError: can't assign to () 

It seems like unpacking rules are not applied for tuples as they are for lists. I cannot think of any explanation for this inconsistency. Is there a reason for this behavior?

like image 892
j0ker Avatar asked Apr 25 '15 19:04

j0ker


1 Answers

The comment by @user2357112 that this seems to be coincidence appears to be correct. The relevant part of the Python source code is in Python/ast.c:

switch (e->kind) {     # several cases snipped     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;     # several more cases snipped } /* Check for error string set by switch */ if (expr_name) {     char buf[300];     PyOS_snprintf(buf, sizeof(buf),                   "can't %s %s",                   ctx == Store ? "assign to" : "delete",                   expr_name);     return ast_error(c, n, buf); } 

tuples have an explicit check that the length is not zero and raise an error when it is. lists do not have any such check, so there's no exception raised.

I don't see any particular reason for allowing assignment to an empty list when it is an error to assign to an empty tuple, but perhaps there's some special case that I'm not considering. I'd suggest that this is probably a (trivial) bug and that the behaviors should be the same for both types.

like image 71
Blckknght Avatar answered Sep 22 '22 20:09

Blckknght