Skip to content

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.
  • Labs icon Lab
  • A Cloud Guru
Google Cloud Platform icon
Labs

Defining and Using Python Generators

Generators are Python functions that behave like iterators. By using generators, we're able to create sequences that are evaluated as each item is needed, making them more memory-efficient compared to simply having lists. In this hands-on lab, we'll be building a generator function that behaves like the built-in `range` function, except it will yield string characters instead of integers. To feel comfortable completing this lab, you'll need to know how to do the following: * Defining and using generators. Watch the "Defining and Using Generators" video from the Certified Entry-Level Python Programmer Certification course. * Working with `for` loops. Watch the "The `for` Loop" video from the Certified Entry-Level Python Programmer Certification course. * Using the `ord` and `chr` functions. Watch the "String Encodings and Functions" video from the Certified Entry-Level Python Programmer Certification course.

Google Cloud Platform icon
Labs

Path Info

Level
Clock icon Beginner
Duration
Clock icon 30m
Published
Clock icon Nov 26, 2019

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Create the char_range Generator

    The first thing that we need to create is the char_range function within the using-generators.py file. Just creating a function doesn't make it a generator. To do that, we need to use the keyword yield. Let's create the function and simply yield the start character for the time being:

    using-generators.py (partial)

    def char_range(start, stop, step=1):
        yield start
    

    Now if we run the file, we should make it past the first check that ensures we've created a generator. You should see the following assertion error:

    $ python3.7 using-generators.py
    Traceback (most recent call last):
      File "using-generators.py", line 23, in <module>
        ], f"Expected ['a', 'b', 'c', 'd', 'e'] but got {repr(list(char_range('a', 'e')))}"
    AssertionError: Expected ['a', 'b', 'c', 'd', 'e'] but got ['a']
    

    Next, we'll need to create a range from our starting character to our ending character by utilizing the Unicode code point for each character. To do this we'll use the ord function, and then we'll yield the result of the chr function and the code point for each item in our range. Here's how we might write this:

    using-generators.py (partial)

    def char_range(start, stop, step=1):
        start_code = ord(start)
        stop_code = ord(stop)
    
        for value in range(start_code, stop_code, step):
            yield chr(value)
    

    Now if we run this, we'll see the following error:

    $ python3.7 using-generators.py
    Traceback (most recent call last):
      File "using-generators.py", line 27, in <module>
        ], f"Expected ['a', 'b', 'c', 'd', 'e'] but got {repr(list(char_range('a', 'e')))}"
    AssertionError: Expected ['a', 'b', 'c', 'd', 'e'] but got ['a', 'b', 'c', 'd']
    

    We're creating the range, but we're not yet being inclusive of the stop character.

  2. Challenge

    Include the Stop Character in the Results

    Now that we're yielding characters properly, we need to deviate from how the range function works to also include the stop character's code point. To do this, we'll add 1 to the stop character when we are creating our range:

    using-generators.py (partial)

    def char_range(start, stop, step=1):
        start_code = ord(start)
        stop_code = ord(stop)
    
        for value in range(start_code, stop_code + 1, step):
            yield chr(value)
    

    Now when we run the file we should see the following error:

    $ python3.7 using-generators.py
    Traceback (most recent call last):
      File "using-generators.py", line 37, in <module>
        ], f"Expected ['e', 'd', 'c', 'b', 'a'] but got {repr(list(char_range('e', 'a')))}"
    AssertionError: Expected ['e', 'd', 'c', 'b', 'a'] but got []
    

    This error is caused by us not being able to create a range from a higher number to a lower number while using a positive step value.

  3. Challenge

    Support the Start Code Point Being More Than the Stop Code Point

    To support creating a range from a higher Unicode code point to a lower one, we'll need to make our step value negative if we see that the code point for start is greater than the code point for stop. We can do this by using a conditional and reassigning the step variable:

    using-generators.py (partial)

    def char_range(start, stop, step=1):
        start_code = ord(start)
        stop_code = ord(stop)
    
        if start_code > stop_code:
            step *= -1
    
        for value in range(start_code, stop_code + 1, step):
            yield chr(value)
    

    Running the file again we can see that this almost works:

    $ python3.7 using-generators.py
    Traceback (most recent call last):
      File "using-generators.py", line 40, in <module>
        ], f"Expected ['e', 'd', 'c', 'b', 'a'] but got {repr(list(char_range('e', 'a')))}"
    AssertionError: Expected ['e', 'd', 'c', 'b', 'a'] but got ['e', 'd', 'c']
    

    The issue here is that we're always adding a positive 1 to our stop character's code point — even if we're stepping in a negative direction. To get around this, we can store the value that we add to the stop_code in a variable and make it negative if we need to negate the step value. Here's what this code change looks like:

    using-generators.py (partial)

    def char_range(start, stop, step=1):
        stop_modifier = 1
        start_code = ord(start)
        stop_code = ord(stop)
    
        if start_code > stop_code:
            step *= -1
            stop_modifier *= -1
    
        for value in range(start_code, stop_code + stop_modifier, step):
            yield chr(value)
    

    Now the stop_modifier variable will adjust based on our step direction. Running the file one last time, we should see no output at all, which indicates that char_range meets all of the predefined expectations.

The Cloud Content team comprises subject matter experts hyper focused on services offered by the leading cloud vendors (AWS, GCP, and Azure), as well as cloud-related technologies such as Linux and DevOps. The team is thrilled to share their knowledge to help you build modern tech solutions from the ground up, secure and optimize your environments, and so much more!

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.

Start learning by doing today

View Plans