I am having some trouble understanding parts of syntax. Particularly when parentheses ()
are required for tuples.
For instance, this piece of code below:
c = {'a':10,'b':1,'c':22,'d':10}
tup = a,b = 4,5
print(a)
print(b)
print(tup)
newlist = [(x,y) for y,x in c.items()]
print(newlist)
The output for this code is:
4
5
(4, 5)
[(10, 'a'), (1, 'b'), (22, 'c'), (10, 'd')]
When trying to take the parentheses out of x, y in the list comprehension statement, I get a traceback. However, every other tuple in this code does not require parenthesis.
What am I missing? Why is it that Python understands a,b
to be a tuple but not x,y
when it is in a list comprehension statement?
It seems to me that Python is inconsistent with tuple syntax. I tried taking the parentheses out and putting them back to understand how the syntax works.
Parentheses are needed to give priority to operators. Consider the two following lines of code, which differ only by the parentheses:
tup_a = 3, 4 + 10, 20
tup_b = (3, 4) + (10, 20)
The first line defines a tuple tup_a
of 3 elements, (3, 14, 20)
. The second line defines two tuples (3, 4)
and (10, 20)
, then concatenates them into a tuple of four elements, (3, 4, 10, 20)
.
Wrong parentheses can easily result in an error:
tup_c = 3, 4 * 10, 20
tup_d = (3, 4) * (10, 20)
The first line defines a tuple of 3 elements, (3, 40, 20)
. The second line results in a TypeError
because it defines two tuples (3, 4)
and (10, 20)
and then attempts to multiply them, but the multiplication operator *
doesn't know what to do with tuples.
You encountered a similar issue. Consider the following lines of codes:
x = 42
c = {'a': 10, 'b': 1, 'c': 22, 'd': 10}
l_a = [(x, y) for y,x in c.items()] # [(10, 'a'), (1, 'b'), (22, 'c'), (10, 'd')]
l_b = [x, (y for y,x in c.items())] # [42, <generator object>]
l_c = [x, y for y,x in c.items()] # SyntaxError: invalid syntax
This code correctly defines two lists l_a
and l_b
, but then it raises a SyntaxError
when trying to define l_c
.
The designers of python decided that the syntax for l_c
was ambiguous, and you should add parentheses to explicitly specify whether you meant the same thing as l_a
or as l_b
.
Note that the line of code for l_b
would raise a NameError: name 'x' is not defined
if I hadn't added x = 42
at the beginning, since the role of x
is not the same in l_b
as it is in l_a
.