In earlier versions of Python, the idea of list comprehensions was introduced to neaten up these two patterns of code:
# Go through each item in a list and run a test on them
# build a new list containing only items that pass the test
results = []
for item in somelist:
if sometest(item):
results.add(item)
and
# build a new list by changing every item in a list in the
# same way
results = []
for item in somelist:
results.add(2 * item)
by adding a new syntax that includes doing all three things in one - changing the items and/or testing them to only include some in the result, and creating the list of the results:
results = [2 * item for item in somelist if sometest(item)]
# results is a list
This feature uses the [] syntax that indicates "list" in Python, and it builds a list right away in memory.
Sometimes you don't want or need the entire list built in memory right away, so later versions of Python introduced generator expressions - the same idea, but they save memory by quickly returning a generator which you can iterate over as if it was a list, and it builds the list as and when you use it.
But they can't have the same syntax and be a direct swap out because they behave slightly differently, so they use () instead of [], e.g.:
somelist = [1,2,3,4,5]
results = (2 * item for item in somelist if sometest(item))
# results is a generator
If you try and call a function with this, you get two layers of parentheses:
function((2 * item for item in somelist))
Which looks silly, so you can leave one out:
function(2 * item for item in somelist)
Which appears to be a standalone backwards for loop on its own, but it actually isn't.
So with parentheses you can write this:
>>> print (item for item in [1,2,3])
<generator object <genexpr> at 0x7fe31b8663c0>
Which is the closest thing to what you wrote that is valid syntax in Python 2.x, but it doesn't do what you expect, and ^^ is what it does and why.
Or this:
>>> print [item for item in [1,2,3]]
[1,2,3]
Which generates a list and prints the list, the other close thing to what you wrote, but still not what you expected.
-- (there really isn't much point in me posting now a bunch other answers have appeared while I was writing this, but eh).
for i in x: print iis the clearest and most explicit way to do that.print(i for i in x), sinceprintis now a function.<generator object <genexpr> at 0x7f2d794b5500>print(list(i for i in x)).list(x)or[i for i in x]which is something else.