Featured resource
pluralsight tech forecast
2025 Tech Forecast

Which technologies will dominate in 2025? And what skills do you need to keep up?

Check it out
Hamburger Icon
  • Labs icon Lab
  • Core Tech
Labs

Guided: Python Basics and Data Structures

Dive into the world of Python with our hands-on course that unpacks the intricacies of its data structures using a delightful cookbook application! You'll grasp concepts like lists, tuples, and dictionaries while also exploring the ins and outs of data organization. Experience firsthand the power of Python comprehensions, navigate the nuances of immutability, and harness Python's flexibility to its fullest. As you craft your very own cookbook command-line application, you'll not only code but also appreciate the 'why' behind every data decision. Whether you're a beginner keen on building a strong foundation or an intermediate user aiming to upskill, this course is tailored just for you. Join us, and let's cook up some Python mastery together!

Labs

Path Info

Level
Clock icon Beginner
Duration
Clock icon 45m
Published
Clock icon Oct 17, 2023

Contact sales

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

Table of Contents

  1. Challenge

    Introduction

    Introduction

    Welcome to the Guided: Python Basics and Data Structures lab.

    At its core, programming is about data and the myriad ways you can manipulate, store, and interact with it. Central to this are data structures, which serve as the foundational building blocks for organizing and representing data. Simply put, a data structure is a particular way of organizing and storing data in a computer so that it can be accessed and modified efficiently.


    Building a Digital Cookbook

    Imagine you're building a digital cookbook app. This app will be your digital sous-chef, helping you store and retrieve various recipes. But how will you organize these recipes? Where will you store the ingredients, the cooking instructions, or the prep time? This is where the choice of the right data structure becomes crucial.

    Before embarking on your culinary coding journey, it's essential to acquaint ourselves with the vast array of data structures available in Python. These structures will be the shelves, drawers, and containers of our digital kitchen, helping us neatly arrange and quickly retrieve each recipe.


    Join In!

    If you wish to experiment as you learn, feel free to use the Python REPL in the first Terminal to the right. It'll serve as your digital playground, allowing you to test, tweak, and tinker with Python's data structures in real-time.

    Ready to stir the pot and cook up some code? Click Next Step > and embark on this delectable journey together!

  2. Challenge

    Understanding Dynamic Typing in Python

    Introduction

    In your journey through Python, it's essential to grasp the concept of dynamic typing, which plays a pivotal role in how variables are handled in the language.


    Definition of Dynamically Typed

    In many programming languages, you have to specify the type of a variable when you declare it. This is not the case with Python, thanks to its dynamically typed nature. Dynamic typing doesn't mean a variable is devoid of a type. Instead, Python automatically determines the type upon the variable's instantiation.

    Consider this example:

    x = "text"
    

    Here, although you haven't explicitly defined x as a string, Python automatically identifies it as such. To confirm the type Python assigns, use the type() function:

    type(x)  # This will return <class 'str'>
    

    Exploring Other Built-in Types

    The str (string) type is just one among Python's fundamental types. Others include int (integer), float, and bool (boolean). Dive into Python's REPL (Read-Eval-Print Loop) to play around with these types:

    y = 1
    type(y)  # This will return <class 'int'>
    

    An intriguing facet of dynamically typed languages is their fluidity concerning variable types. A variable's type can evolve during the program's execution. For instance:

    y = 1.0
    type(y)  # This will return <class 'float'>
    

    While the original type of y was an integer, reassigning it to a floating-point number changed its type dynamically.


    A Double-edged Sword: Potential Errors with Dynamic Typing

    Python's dynamic typing can be both a boon and a bane. On one hand, it offers flexibility and rapid development. On the other, it can lead to potential runtime errors if not handled with care.

    For instance, when you combine incompatible types in Python, it can result in exceptions. If you try the following in the REPL, you will notice a TypeError since you're trying to add a str (string) and a float.

      result = x + y  # Throws a TypeError exception
    

    Such mismatches are a common pitfall for beginners. The key is to be cognizant of the variable types you're working with, especially when performing operations that combine them.


    In summary, Python's dynamic typing offers freedom and flexibility, but with a degree of responsibility. By understanding and anticipating potential pitfalls, you can harness the advantages of dynamic typing while sidestepping its challenges.

    Click the Next step > to continue your exploration of Python Data Structures.

  3. Challenge

    Python Collection Data Types

    In your Python journey, you've already encountered basic types like integers, strings, and floats. However, often in programming, there's a need to group multiple items together. Python provides "collection" data types for this very purpose.


    List Data Type

    Imagine you need to store a collection of various items, maintaining their order. Python’s List is your best companion for this task. You can visualize it as a line of books on a shelf, where you can easily access a book based on its position.

    Create a list using square brackets []:

    l = ['first', 'second']
    type(l)
    

    Items in a list are accessed by their position, starting from 0:

    print(l[0])  # Outputs 'first'
    # If using the REPL you can just type the variable
    l[0]
    

    Python provides numerous methods to manipulate lists. Here are a few:

    l.append('fourth')     # Adds 'third' to the end  
    l.insert(2, 'third')  # Inserts 'third' at position 3
    l.remove('first')     # Removes the 'first' item
    

    Lists are versatile. They can hold different data types, including other lists:

    l = [[1,2,3], [4,5,6]]
    

    In essence, when you need an ordered collection, think List.


    Tuple Data Type

    Tuples are like lists with one crucial distinction: they're immutable. This means once you've created a tuple, you can't modify it. This characteristic is handy when you want your data to remain constant.

    To create a tuple, use parentheses ():

    t = ('first', 'second', 'third')
    

    Accessing elements is similar to lists:

      t[1]  # Outputs 'second'
    

    Tuples can also contain other collection data types, such as a List

    t = ([1, 2], [4, 5, 6])
    

    A common misconception about tuples is that their entire content is immutable. In reality, it's only the first level of the tuple that's immutable. This means that while you cannot add or remove items from a tuple itself, if the tuple contains mutable objects, such as lists, you can modify the contents of those internal objects.

    t[0].append(3)
    t  # Outputs ([1, 2, 3], [4, 5, 6])
    

    Remember, the power of tuples lies in their immutability. When you need data that shouldn’t change, choose Tuple.


    Set Data Type

    Ever needed a collection where every item is unique and order doesn't matter? Enter the Set. It ensures that duplicates are not allowed.

    Define a set using curly braces {}:

    s = {1, 2, 3}
    

    You can add items, but remember, duplicates are automatically discarded:

    s.add(4)
    s.add(3)  # No effect, as 3 is already in the set
    s # Outputs {1, 2, 3, 4}
    

    However, be cautious about what you insert. Items in a set need to be hashable, meaning you can't add mutable types like lists:

    # This raises an error:
    s = {[1,2,3], [4,5,6]}
    

    For collections that need uniqueness, Set is your go-to.


    Dictionary Data Type

    Dictionaries are perfect when you want to associate names (keys) with values. Think of it as an English dictionary, where you look up a word (key) to get its definition (value).

    Define a dictionary using curly braces {} with key-value pairs:

    d = {"item": "laptop", "quantity": 10, "price": 400.00}
    

    Access values by their associated keys:

    d["item"]  # Outputs 'laptop'
    

    Dictionaries are invaluable when you need to label your data, making your code more descriptive and intuitive.


    To conclude, Python's collection types offer diverse ways to group and manage data. As you progress, you'll find scenarios where one type is more fitting than the others. Remember, the goal is to make your code clearer and more efficient.

    Continue your journey by click the Next step > to see how these can be combined to create complex objects.

  4. Challenge

    Designing the CookBook Structure

    Designing the Recipe Data Structure

    Now that you've learned about Python's fundamental data structures, apply this knowledge to design a data model for your cookbook application.


    Understanding Recipe Components


    Recipe Name:

    Each recipe needs to be identified in some manner.

    What data type do you think would be best for identifing each recipe?

    🔍 Considerations: At first glance, a simple string value seems appropriate, like: "Pancakes". However, always analyze the specific requirements of a field before settling. What if, hypothetically, a recipe needed multiple names for reference? Imagine pancakes also being known as hot cakes or flapjacks. Such requirements would influence your choice of data structure.

    But for the current cookbook application, there's no such complexity. Thus, a straightforward string is perfect.

    name = "Pancakes"
    

    Ingredients:

    Each recipe contains multiple ingredients.

    When analyzing this component, it's beneficial to first examine an individual ingredient. Typically, an ingredient has a:

    • item (e.g., "flour")
    • quantity (1, "1/2", "2 cups")
    • measurement ("cups", "tsp" ) - if not provided directly in the quantity

    What data type would best represent an individual ingredient?

    🔍 Considerations: Given that each ingredient comprises various related details, the key-value nature of a dictionary emerges as the clear choice.

    Consider the following possible structures:

    ingredient_1 = {"item": "eggs", "quantity": 2}
    ingredient_2 = {"item": "milk", "quantity": "1/2 cup"}
    ingredient_3 = {"item": "flour", "quantity": 1, "measurement": "cup"}
    
    • When choosing a structure, think about how each data element will be used within your application. For example, if you need to store a numeric quantity, you might also want a separate measurement value. However, using a string to represent quantity can be tricky. You could run into issues, like getting a TypeError, if other parts of your app are expecting a number.

    • While Python's dynamic typing offers a lot of flexibility, it's essential to plan ahead. Taking the time to think about how you model your data can help avoid potential problems later on.


    Collection of Ingredients

    Now that an individual ingredient has been structured, you can now consider how a collection of ingredients can be structured.

    What data type would be best for storing a collection of ingredients?

    🔍 Considerations: Generally, recipes do not list ingredients in a strict order. They're mainly listed to help the cook know what will be needed for the recipe. With that in mind consider which collection type might be best to store the ingredients. * **Set**: At first glance, since order does not matter, a Set might seem like a good fit. But Sets don't allow duplicates and can only hold hashable items, which means dictionaries can't be stored in them. * **Tuple**: A Tuple can hold a group of ingredient dictionaries. But remember, a Tuple is immutable and you can't add to a Tuple after it's created, so it's not ideal if you need to update recipes after initialization. * **List**: Even though order might not be crucial, a List's flexibility makes it an excellent option for storing dictionaries of ingredients.
    ingredients = [
     {"item": "eggs", "quantity": "2"},
     {"item": "milk", "quantity": "1/2 cup"},
     {"item": "flour", "quantity": 1, "measurement": "cup"}
    ]
    

    Recipe Instructions

    Each recipe has a set of steps, consisting of string sentences, to guide the cook on completing the recipe

    What data type would be best for storing a collection of ingredients?

    🔍 Considerations: Unlike the list of ingredients, the instructions for a recipe need to be followed in a specific sequence. Imagine the chaos of baking raw ingredients before mixing them! Given the importance of order, the choice narrows down to either a Tuple or a List.
    • Tuple: Tuples preserve the order of items. However, they're immutable, meaning you can't change them once they're set.
    • List: Lists also keep the order intact and offer the advantage of being mutable, allowing modifications at runtime.

    Your decision hinges on the application's needs. If ensuring that the instructions remain unchanged is crucial, a Tuple is ideal. On the other hand, Lists offer both order and flexibility. In the absence of stringent requirements to keep the instructions static, the simpler and more adaptable choice would be a List.

    instructions = [
     "Mix all ingredients", 
     "Pour batter into pan", 
     "Cook until golden brown"
    ] 
    

    Putting it All Together

    Having delved into the individual components of a recipe, it's time to bring everything together.

    Which data structure in Python is best equipped to consolidate these diverse elements?

    🔍 Considerations: Given that a recipe has clearly defined components such as `name`, `ingredients`, and `instructions`, a dictionary is a natural fit. Each component can be represented as a key-value pair in the dictionary.

    In the recipes.py file to the right, add one or more recipe items based on your chosen data structure. Once done, expand the Solution to see how yours compares.

    🔑 Solution: For example a recipe could look like: ```python recipe = { "name": "Pancakes", "ingredients": [ {"item": "eggs", "quantity": "2"}, {"item": "milk", "quantity": "1/2 cup"}, {"item": "flour", "quantity": "1 cup"} ], "instructions": [ "Mix all ingredients together", "Pour batter on pan", "Cook until golden brown" ] } ```

    Note: This "solution" is not the only one, just the one chosen for this lab. If your solution is different, feel free to continue using that. Just be aware that the following steps are based on the above structure and you may need to adjust the recommend code.

  5. Challenge

    Building the CookBook Application

    With the data structure for your cookbook recipes in place, it's time to progress with building the application. The file cookbook.py provided on the right initiates this process.

    This Python script greets you with a couple of simple command line options to interact with.


    Running the Application

    You can execute the application by using the second Terminal to the right. Type in and run the following command:

    python3 cookbook.py
    

    When you choose either of the provided options, you'll observe that nothing gets returned, not even the recipes. Navigating further down the cookbook.py file, you'll come across the segment where the command line options are displayed. Following this is the logic determining which function gets triggered based on your selection.


    Implementing the "List Recipes" Option Using a for Loop

    The first command line option - "List Recipes", directs the code to invoke the list_recipes() function. If you examine this function, currently, it merely has the pass statement, which essentially means it's a placeholder and does nothing.

    Your goal is to enhance this function such that it displays the list of available recipe names.


    Iterating Over a Collection with for

    Python provides the versatile for loop to traverse through collections like lists. Here's a fundamental way to employ it:

    items = ["one", "two", "three"]
    for item in items:
        print(item)
    

    In light of this, modify the list_recipes() function to print() the name of every recipe stored within the recipes list.

    🔍 Considerations: * The variable you use in the `for` loop (like `item` in the example) is arbitrary. You can use something more descriptive like `recipe`. * On each iteration, this variable (e.g., `recipe`) holds the data of a single recipe. Since a recipe is structured as a dictionary, to fetch the name of a recipe, you'd utilize `recipe['name']`.
    🔑 Solution:
    def list_recipes():
        for recipe in recipes:
            print(recipe['name'])
    

    Implementing the "Query Recipes" Option Using Comprehensions

    The "Query Recipes" option invokes the query_recipes() function. Upon execution, the user will be prompted to enter a recipe name. The goal is to filter the existing recipes and retrieve those that match the user-provided name, populating the results into the found_recipes variable. Presently, found_recipes is merely set to None.

    Leveraging Comprehensions for Efficient Collection Iteration

    While a traditional for loop can be employed to scan the list of recipes and compare the recipe['name'] with the user provided name, Python offers a more concise and readable solution known as Comprehensions. Comprehensions enable quick iteration over collections, simultaneously facilitating collection transformation or filtration.

    Consider the example below where a list is filtered based on items containing the letter "o":

    items = ["one", "two", "three"]
    filtered = [item for item in items if "o" in item]
    

    The filtered list will now consist of the entries "one" and "two".


    Applying Comprehensions to query_recipes()

    Utilize a comprehension within the query_recipes() function to populate found_recipes with recipe entries aligning with the user's input.

    🔍 Considerations: * The core of the comprehension mirrors a `for` loop. It will yield the familiar `recipe` object, similar to traditional iteration. * User input can be unpredictable in its case-sensitivity. To ensure accurate matches regardless of input casing (e.g., "Pancakes" vs "pancakes"), utilize the `.lower()` method to standardize comparisons.
    🔑 Solution
    found_recipes = [recipe for recipe in recipes if query_name.lower() in recipe["name"].lower()]
    
    By integrating comprehensions, you can effortlessly iterate over the `recipes` list and procure relevant matches in an elegant and Pythonic fashion.

    Enhancing the User Experience

    While the basic functionality is in place, consider adding features like error handling, displaying only specific details of the recipe (like ingredients or preparation steps), or even incorporating a search by ingredient option. The potential to refine and expand this application is vast, offering a rich learning experience as you implement each new feature.

    Wishing you success in your Python journey! Excited to see what you create next!

Jeff Hopper is a polyglot solution developer with over 20 years of experience across several business domains. He has enjoyed many of those years focusing on the .Net stack.

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.