DEV Community

Super Kai (Kazuya Ito)
Super Kai (Kazuya Ito)

Posted on • Edited on

Generator in Python (1)

Buy Me a Coffee

*Memo:

A generator:

  • is the function which has one or more yield statements to return an iterator and whose type is generator:
  • 's iterator can be created by a generator comprehension:
    • A generator comprehension is an expression.
  • 's iterator cannot be copied.
  • can use throw(), close(), send(), gi_yieldfrom, gi_running and gi_suspended.
  • 's yield statement can be assigned to a variable.
  • 's yield statement cannot be assigned to a for statement.
  • terminates if there are no elements to return, if close() is called or of course if error occurs.

A generator can be created with a function and one or more yield statements and read with next() as shown below:

*Memo:

  • __next__() can also be used to read a generator.
  • A yield statements is a yield or yield from.
  • A yield can return any type of element.
  • A yield from can only return an iterable.

<yield>:

def gen(): yield 0 yield 1 yield 2 print(gen) # <function func at 0x000001FCD2FF93A0> print(type(gen)) # <class 'function'>  v = gen() print(v) # <generator object func at 0x000001FCD3015220> print(type(v)) # <class 'generator'>  print(next(v)) # 0 print(next(v)) # 1 print(next(v)) # 2 print(next(v)) # StopIteration: 
Enter fullscreen mode Exit fullscreen mode
def gen(): yield [0, 1, 2] yield [3, 4, 5] v = gen() print(next(v)) # [0, 1, 2] print(next(v)) # [3, 4, 5] print(next(v)) # StopIteration: 
Enter fullscreen mode Exit fullscreen mode

<yield from>:

def gen(): yield from [0, 1, 2] yield from [3, 4, 5] print(gen) # <function func at 0x000001FCD640B1A0> print(type(gen)) # <class 'function'>  v = gen() print(v) # <generator object func at 0x000001FCD661DD80> print(type(v)) # <class 'generator'>  print(next(v)) # 0 print(next(v)) # 1 print(next(v)) # 2 print(next(v)) # 3 print(next(v)) # 4 print(next(v)) # 5 print(next(v)) # StopIteration: 
Enter fullscreen mode Exit fullscreen mode
def gen(): yield from 0 yield from 1 yield from 2 v = gen() print(next(v)) # TypeError: 'int' object is not iterable 
Enter fullscreen mode Exit fullscreen mode

<yield & yield from>:

def gen(): yield [0, 1, 2] yield from [3, 4, 5] v = gen() print(next(v)) # [0, 1, 2] print(next(v)) # 3 print(next(v)) # 4 print(next(v)) # 5 print(next(v)) # StopIteration: 
Enter fullscreen mode Exit fullscreen mode

This is how a generator works as shown below:

*Memo:

  • next() starts or resumes a generator, executes a yield statement to return a value and pauses the generator at a yield statement or raises StopIteration if a generator is terminated:
  • A generator is always paused at a yield statement.
  • __next__() also does the same things.

<yield>:

def gen(): print('gen() starts.') yield 'gen() pauses.' print('gen() resumes.') yield 'gen() pauses again.' print('gen() resumes again.') yield 'gen() terminates.' v = gen() # `gen()` doesn't start yet.  print(next(v)) # gen() starts. # gen() pauses.  print(next(v)) # gen() resumes. # gen() pauses again.  print(next(v)) # gen() resumes again. # gen() terminates.  print(next(v)) # StopIteration: 
Enter fullscreen mode Exit fullscreen mode

<yield from>:

def gen(): print("gen() starts.") yield from ["gen() pauses.", "gen() resumes and pauses."] print("gen() resumes.") yield from ["gen() pauses.", "gen() resumes and terminates."] v = gen() # `gen()` doesn't start yet.  print(next(v)) # gen() starts. # gen() pauses.  print(next(v)) # gen() resumes and pauses.  print(next(v)) # gen() resumes. # gen() pauses.  print(next(v)) # gen() resumes and terminates.  print(next(v)) # StopIteration: 
Enter fullscreen mode Exit fullscreen mode

This is the generator with a for statement as shown below:

<yield>:

def gen(): for x in [0, 1, 2]: yield x v = gen() print(next(v)) # 0 print(next(v)) # 1 print(next(v)) # 2 print(next(v)) # StopIteration: 
Enter fullscreen mode Exit fullscreen mode
def gen(): for x in [[0, 1, 2], [3, 4, 5]]: yield x v = gen() print(next(v)) # [0, 1, 2] print(next(v)) # [3, 4, 5] print(next(v)) # StopIteration: 
Enter fullscreen mode Exit fullscreen mode

<yield from>:

def gen(): for x in [[0, 1, 2], [3, 4, 5]]: yield from x v = gen() print(next(v)) # 0 print(next(v)) # 1 print(next(v)) # 2 print(next(v)) # 3 print(next(v)) # 4 print(next(v)) # 5 print(next(v)) # StopIteration: 
Enter fullscreen mode Exit fullscreen mode
def gen(): for x in [0, 1, 2]: yield from x v = gen() print(next(v)) # TypeError: 'int' object is not iterable 
Enter fullscreen mode Exit fullscreen mode

<yield & yield from>:

def gen(): for x in [[0, 1, 2], [3, 4, 5]]: yield x yield from x v = gen() print(next(v)) # [0, 1, 2] print(next(v)) # 0 print(next(v)) # 1 print(next(v)) # 2 print(next(v)) # [3, 4, 5] print(next(v)) # 3 print(next(v)) # 4 print(next(v)) # 5 print(next(v)) # StopIteration: 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)