In Python 3, print() is a function, not a statement.
A generator expression is like a list comprehension, except it creates an object that produces results when you iterate over it, not when you create it. For example,
[i*i for i in range(5)]
produces a list, [0, 1, 4, 9, 16], while
(i*i for i in range(5))
produces a generator object that will produce those numbers when you iterate over it.
If you give a function only one argument and it is a generator expression, you can omit the parentheses around the generator expression, so you do not have to do myfunc((i + 1 for i in something)).
So you are creating a generator object, and passing it to the print() function, which prints its representation. It’s doing exactly what you asked for, just not what you meant to ask for.
You can initialize a list from a generator expression:
print(list(i*i for i in range(5)))
but it is easier to use the list comprehension:
print([i*i for i in range(5)])
A simple example of how you might use the generator object is:
for value in (i * i for i in range(5)):
print value
although in that simple example it would obviously be easier to write:
for i in range(5):
print i * i