DEV Community

Ugbem Job
Ugbem Job

Posted on

Day 7: Generators

What I learnt

  • Generators
  • Range
  • Yield
  • Generator Expressions
  • Generator Functions
  • Generator Comprehensions

Generators

Generators in Python are functions that allow you to iterate over a sequence of values without creating a list in memory. Generators are used to create iterators, but with a different approach than the usual functions. Instead of returning all the values at once, generators return them one at a time, which makes them more memory efficient.
In simple terms; generators are a special type of function that return an iterable set of items, one at a time, in a special way.

Generator functions are functions that return a generator object some examples of generator functions are range(), enumerate() etc.

  • range() - This is a built-in generator function that takes in two parameters (start and stop) and returns an iterator object that can be used to iterate over the sequence of numbers from start to stop.
  • enumerate() - This is another built-in generator function that takes in an iterable object and returns an iterator object with index-value pairs for each element in the given iterable object.
  • yield - The yield keyword is used inside generator functions to return values one at a time instead of returning all the values at once.

Example

num_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

def square_numbers(nums):
    result = []
    for i in nums:
        result.append(i * i)
    return result

square_num = square_numbers(num_list)
print(square_num)  # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Enter fullscreen mode Exit fullscreen mode

The above code is returning a list and it is not memory efficient. We need to use generators to solve this problem.

def square_numbers(nums):
    for i in nums:
        yield i * i

square_num = square_numbers(num_list)
<generator object square_numbers at 0x7f9b8c0b9f50>
print(square_num)
print(next(square_num))  # This will return the next value in the generator object until there are no more values to return.
Enter fullscreen mode Exit fullscreen mode

Instead of returning a list, the above code is returning a generator object. We can iterate over the generator object to get the values one at a time.

To get all the values from the generator object, we can use a for loop.

for num in square_num:
    print(num)  # 1 4 9 16 25 36 49 64 81 100
Enter fullscreen mode Exit fullscreen mode

Python Generators vs List Comprehension

  • List Comprehension: is a concise way to create lists in Python. It is a very powerful tool that can be used to create lists in a very efficient way.

Example

squares = [i * i for i in range(1, 11)]
print(squares)  # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Enter fullscreen mode Exit fullscreen mode
  • Generators: are a special type of function that return an iterable set of items, one at a time, in a special way. Generators are memory efficient and are used to create iterators.
def square_numbers(nums):
    for i in nums:
        yield i * i

square_num = square_numbers(range(1, 11))
 print(square_num)  # <generator object square_numbers at 0x7f9b8c0b9f50>

for num in square_num:
    print(num)  # 1 4 9 16 25 36 49 64 81 100

Enter fullscreen mode Exit fullscreen mode

Using list comprehension

squares = [i * i for i in range(1, 11)]
print(squares)  # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Enter fullscreen mode Exit fullscreen mode

Using a generator expression

squares = (i * i for i in range(1, 11))
print(squares)  # <generator object <genexpr> at 0x7f9b8c0b9f50>
Enter fullscreen mode Exit fullscreen mode

Exercise:

  • Write a generator function that takes in two numbers (start and end) as parameters and yields all the even numbers between start and end (inclusive).
def even_numbers(start, end):
    for i in range(start, end + 1):
        if i % 2 == 0:
            yield i

my_even_numbers = even_numbers(1, 50)
for num in my_even_numbers:
    print(num)

Enter fullscreen mode Exit fullscreen mode
  • Write a generator function that takes in two numbers (start and end) as parameters and yields all the prime numbers between start and end (inclusive).
def prime_numbers(start, end):
    for i in range(start, end + 1):
        if i > 1:
            for j in range(2, i):
                if i % j == 0:
                    break
            else:
                yield i


my_prime_numbers = prime_numbers(1, 50)
for num in my_prime_numbers:
    print(num)

Enter fullscreen mode Exit fullscreen mode

Conclusion

In this article, we learnt about generators and how to use them. We also learnt about how much more efficient generators are compared to lists. So the next time you need to create a list of values, you should consider using generators instead of list comprehensions.

Resources

Please contact me through Twitter or LinkedIn if you have any questions or recommendations.

Additionally, do leave a comment below if you have any queries or recommendations. I'd love to hear from you, and please share this post with your friends and subscribe to Dev.to for more articles like this.
Thank you for taking the time to read this.

Top comments (0)