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.
