Why is this code
sum(x for x in range(10))
valid? Why encasing x for x in range(10)
in square brackets is not necessary?
Why is this code
sum(x for x in range(10))
valid? Why encasing x for x in range(10)
in square brackets is not necessary?
I think this has pretty much already been said in comments, but for posterity: Section 6.2.8 of the (Python 3.8.0) docs state that "[t]he parentheses can be omitted on calls with only one argument. See section Calls for details."
Edit: And, for completeness, the "Calls" section goes on to say that the actual parameters of a call can be either a comma-separated list of parameters, or a single comprehension
, which is the x for x in ...
stuff without brackets.
It creates a generator expression.
>>> nums = (x for x in range(4))
>>> nums
<generator object <genexpr> at 0x000001E52747B2B0>
>>> next(nums)
0
>>> next(nums)
1
>>> next(nums)
2
>>> next(nums)
3
>>> next(nums)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
What is a generator? It basically doesn't execute unless it is asked to execute. A list comprehension will first create a list
and then pass that list
to the sum
function.
Getting rid of the square brackets makes it a generator which will send each generated value to sum
without creating the list explicitly. sum
will keep asking for numbers from the genexpr
and stop when StopIteration
is raised. This is faster than using a list comprehension.
If you have a very long sequence, and you use a list comprehension with the sum function, python will first take time to generate the entire list and then sum will again calculate the sum of all the elements. Using a generator expression with sum will reduce a lot of execution time because sum will get each value as soon as it is generated.