What is the proper difference between doing yield i from an iteration and return (i for i in range(10)).
def generator1():
    for i in range(10):
        yield i
def generator2():
    return (i for i in range(10))
For example, see these functions generator1() and generator2() both are differently written but both return a generator.
Outputs of IDLE:-
>>> generator1()
>>> <generator object generator1 at 0x107870468>
>>> generator2()
>>> <generator object generator2.<locals>.<genexpr> at 0x107870db0>
>>> import sys
>>> sys.getsizeof(generator1())
>>> 88
>>> sys.getsizeof(generator2())
>>> 88
As we can tell generator2() has fewer LOC (line of code) than generator2 and also the size of the object is the same, I've some questions.
- What is the difference between both functions?
- What does <genexpr>means when printinggenerator2()?
- Which is the more suitable and efficient way of creating a generator?
 
    