Course 2: Functions, Lists, Dictionaries & Loops
This course builds on the basics of Python programming, focusing on functions, lists, dictionaries, and loops. Designed for learners who have grasped Python's fundamentals, this course introduces key data structures and programming constructs essential for data analysis. Over one week, daily lessons cover function definitions, list and dictionary operations, loop iterations, and their practical applications, providing a robust foundation for intermediate Python programming.
Objective: By the end of the course, students will be able to define and use functions, manipulate lists and dictionaries, iterate over data structures with loops, and apply these skills to solve real-world data analysis problems.
Scope: The course covers function creation, list and dictionary operations, loop iterations, and practical applications in data processing, preparing learners for advanced topics like data manipulation and analysis.
Day 1: Introduction to Functions
Introduction: Functions are essential building blocks in Python programming. They allow you to define reusable code blocks, which enhances efficiency and readability. Functions help avoid redundancy, ensuring your code is cleaner and more maintainable. They are frequently used in data analysis tasks, such as calculations or data processing, where a certain operation is performed multiple times across a program. By organizing code into distinct functions, developers can improve modularity, making the overall codebase more organized and less error-prone.
Learning Objective: The objective of this lesson is to teach you how to define, call, and use functions in Python. You will learn how to pass parameters into functions, use return statements to send results back, and understand the scope of variables (local and global) to manage data within your functions.
Scope of the Lesson: This lesson covers how to define functions using the def keyword and how to pass parameters to functions. Additionally, you'll learn how to define return values, which allow functions to send data back to the calling code. The lesson also covers default arguments, which provide fallback values when no argument is passed by the user. Furthermore, the lesson explains the importance of variable scope, discussing the difference between local and global variables and how to access or modify them within a function. By the end of the lesson, you'll have a solid foundation in defining and using functions to streamline your Python code.
Background Information: In Python, functions are defined using the def keyword followed by the function's name, a set of parentheses, and a colon. The parameters placed inside the parentheses are the inputs that the function expects. For example, if you are defining a function that adds two numbers together, you would specify the parameters that represent those numbers. After the colon, the body of the function is indented, and it contains the code to perform the desired operation, such as returning a value using the return keyword. A function may take one or more parameters, and these parameters are used as inputs when the function is called. If no argument is passed for a parameter, a default value can be used, which makes the function more flexible. For example, if a function accepts an argument for a name but you don’t pass one, the function can use a default name like "Guest" to personalize a greeting message. The return statement is used to send back the result from a function to the calling code. When a function returns a value, you can assign it to a variable or use it directly in an expression. Functions can also perform tasks without returning anything, such as printing a message to the console. Python’s variable scope is an important concept when working with functions. Variables inside a function are local to that function, meaning they exist only while the function is running and cannot be accessed outside of it. However, variables defined outside the function are global and can be accessed within any function. If you want to modify a global variable inside a function, the global keyword is used to indicate that the variable should be updated outside the function.
Examples to Practice:
# Example 1: Basic function with parameters def add(a, b): return a + b print(add(3, 5)) # Output: 8 # Example 2: Function with default arguments def greet(name="Guest"): return f"Hello, {name}!" print(greet()) # Output: Hello, Guest! print(greet("Alice")) # Output: Hello, Alice! # Example 3: Function without parameters def say_hello(): print("Hello, World!") say_hello() # Output: Hello, World! # Example 4: Using return to calculate a value def multiply(a, b): result = a * b return result print(multiply(4, 3)) # Output: 12 # Example 5: Local vs Global variables x = 10 # Global variable def test_scope(): x = 5 # Local variable print(f"Local x: {x}") test_scope() # Output: Local x: 5 print(f"Global x: {x}") # Output: Global x: 10
Explanation of the Example Codes & Outputs: In Example 1, the function add() accepts two parameters, a and b, and returns their sum. The result is 8 when called with 3 and 5. Example 2 demonstrates the use of default arguments. If no argument is passed to the function greet(), it uses "Guest" as the default name. Example 3 shows a function without parameters, say_hello(), which prints "Hello, World!". Example 4 calculates the product of two numbers with the multiply() function, returning the result of the multiplication. Finally, Example 5 highlights the concept of variable scope. The test_scope() function creates a local variable x, which does not affect the global variable x, demonstrating how Python distinguishes between local and global scopes.
Supplemental Information: Functions are one of the key building blocks for effective programming. They allow for code reuse, which reduces the need for repeated code and ensures a more maintainable and modular codebase. Python’s functions are versatile, offering features like default arguments, variable-length arguments, and the ability to handle local and global variables. As you advance in Python, understanding how to leverage functions will greatly improve your efficiency, especially in large data analysis projects. This lesson sets the foundation for writing clean and efficient Python code.
Resources:
Day 2: Lists and List Operations
Introduction: Lists are one of the most commonly used data structures in Python. They allow you to store ordered collections of items, which can be of any data type. Lists are particularly important in data analysis, where datasets are often represented as lists of values. These data structures are mutable, meaning their content can be changed after creation, making them ideal for tasks where data is manipulated over time. The ability to work with lists is essential for handling and analyzing data effectively.
Learning Objective: The objective of this lesson is to teach you how to create, manipulate, and perform operations on lists in Python. By the end of the lesson, you will be proficient in creating lists, accessing elements through indexing, slicing lists, and using common list methods. Additionally, you'll learn how to leverage list comprehensions to generate new lists in a more efficient and readable way.
Scope of the Lesson: This lesson will cover the basics of list creation and how to manipulate lists using various methods such as append(), remove(), and pop(). You will learn about indexing to access individual elements of a list, and slicing to extract subsets of data. Additionally, you'll dive into list comprehensions, which are powerful tools for creating new lists in a concise and readable manner. Understanding these operations will allow you to handle and process data efficiently in your Python programs.
Background Information: In Python, lists are defined by enclosing a collection of elements in square brackets, like so: [1, 2, 3]. Lists are zero-indexed, meaning the first element is at index 0, the second at index 1, and so on. Lists can store elements of any data type, and you can even have lists that contain other lists. The elements within a list are mutable, so you can modify them directly. Indexing in a list allows you to access individual elements by their position. For example, if you have a list my_list = [10, 20, 30], my_list[0] would return 10. Slicing allows you to extract a subset of the list using the syntax my_list[start:end], where the list starts at the start index and ends just before the end index. List methods like append() add elements to the end of the list, while remove() removes the first occurrence of a specified element, and pop() removes and returns an element at a given index. List comprehensions are a concise way to create new lists by applying an expression to each element in an existing list or iterable. For example, [x * 2 for x in range(5)] creates a new list by multiplying each element in the range by 2. List comprehensions are not only shorter but also more readable and often more efficient than using loops.
Examples to Practice:
# Example 1: List creation and indexing my_list = [1, 2, 3, 4, 5] print(my_list[2]) # Output: 3 # Example 2: List slicing my_list = [1, 2, 3, 4, 5] print(my_list[1:4]) # Output: [2, 3, 4] # Example 3: Using append() to add elements to the list my_list = [1, 2, 3] my_list.append(4) print(my_list) # Output: [1, 2, 3, 4] # Example 4: Using remove() to delete an element from the list my_list = [1, 2, 3, 4, 5] my_list.remove(3) print(my_list) # Output: [1, 2, 4, 5] # Example 5: Using list comprehension to create a new list my_list = [x * 2 for x in range(5)] print(my_list) # Output: [0, 2, 4, 6, 8]
Explanation of the Example Codes & Outputs: In Example 1, the list my_list is created, and we access the element at index 2, which is 3. Example 2 demonstrates list slicing, where we extract a portion of the list from index 1 to 3, resulting in the sublist [2, 3, 4]. Example 3 shows how to add an element to the end of a list using the append() method, adding 4 to my_list. Example 4 demonstrates the use of the remove() method, which removes the first occurrence of 3 from the list, resulting in [1, 2, 4, 5]. Finally, Example 5 illustrates list comprehensions by creating a new list that contains the even numbers from 0 to 8 by multiplying each element in the range by 2.
Supplemental Information: Lists are a versatile and powerful data structure in Python, especially in data analysis. They provide an ordered, mutable collection of items that can hold mixed data types, making them highly flexible for storing and manipulating data. Mastering list operations such as slicing, appending, and using list comprehensions will significantly improve your ability to process and transform data efficiently. Additionally, methods like remove() and pop() allow for fine-grained control over list contents, enabling you to easily modify and clean data as needed.
Resources:
- Cheatsheet: Python Lists Cheatsheet (PDF)
- Video: Python Lists by Corey Schafer
- Book: Python for Data Analysis by Wes McKinney
Day 3: Dictionaries and Dictionary Operations
Introduction: Dictionaries are powerful data structures in Python that store data as key-value pairs, making them highly efficient for tasks requiring fast lookups, such as mapping categories or storing metadata. Unlike lists, which store data sequentially, dictionaries offer constant-time access to values when the key is known. This makes them a critical tool in data analysis, where fast access to large datasets is often necessary.
Learning Objective: The objective of this lesson is to teach you how to create, access, and manipulate dictionaries in Python. By the end of the lesson, you will understand how to work with key-value pairs, access data, and use useful methods such as keys(), values(), and items(). You will also learn how to use dictionary comprehensions to create dictionaries efficiently.
Scope of the Lesson: This lesson will cover dictionary creation, accessing dictionary values, and various methods for interacting with dictionaries. You will learn how to access dictionary values using keys or the get() method, how to iterate over dictionary items, and how to retrieve just the keys or values. Additionally, we will explore dictionary comprehensions, which allow for the concise creation of dictionaries using an expression, similar to list comprehensions. Understanding these operations will enable you to effectively store and retrieve structured data in your Python programs.
Background Information: In Python, dictionaries are defined using curly braces {}, with keys and values separated by a colon, like so: {"name": "Alice", "age": 25}. Keys in dictionaries must be unique and immutable, meaning they can be strings, numbers, or tuples, but not lists. Values associated with keys can be of any type, such as integers, strings, lists, or even other dictionaries. You can access the values of a dictionary by specifying the key inside square brackets, like my_dict["name"]. Alternatively, the get() method provides a safer way to retrieve values, as it returns None instead of raising an error if the key is not found. Python dictionaries also come with several useful methods. The keys() method returns a view of all the dictionary’s keys, values() returns a view of all the values, and items() returns a view of all key-value pairs. These methods are useful for iterating over dictionary components and performing tasks like searching or modifying the data. Dictionary comprehensions are a concise and powerful way to create dictionaries. For example, {k: v for k, v in zip(keys, values)} generates a dictionary from two lists, keys and values. This is particularly useful for quickly creating dictionaries based on existing data.
Examples to Practice:
# Example 1: Dictionary creation and accessing values my_dict = {"name": "Alice", "age": 25} print(my_dict["name"]) # Output: Alice # Example 2: Using get() to access values safely my_dict = {"name": "Alice", "age": 25} print(my_dict.get("age")) # Output: 25 print(my_dict.get("gender", "Not Provided")) # Output: Not Provided # Example 3: Using keys(), values(), and items() methods my_dict = {"name": "Alice", "age": 25} print(my_dict.keys()) # Output: dict_keys(['name', 'age']) print(my_dict.values()) # Output: dict_values(['Alice', 25]) print(my_dict.items()) # Output: dict_items([('name', 'Alice'), ('age', 25)]) # Example 4: Dictionary comprehension keys = ["name", "age"] values = ["Alice", 25] my_dict = {k: v for k, v in zip(keys, values)} print(my_dict) # Output: {'name': 'Alice', 'age': 25}
Explanation of the Example Codes & Outputs: In Example 1, a dictionary my_dict is created with two key-value pairs. We access the value associated with the key "name", which returns "Alice". In Example 2, the get() method is used to safely retrieve the value associated with "age", and when a key does not exist ("gender"), it returns a default value of "Not Provided". Example 3 demonstrates the use of keys(), values(), and items() to access all the keys, values, and key-value pairs in the dictionary. Lastly, Example 4 illustrates dictionary comprehension, where we combine two lists (keys and values) into a dictionary using a concise expression.
Supplemental Information: Dictionaries are an essential part of Python and are particularly useful when working with structured data. They provide fast access to values, and the ability to create dictionaries dynamically through comprehensions makes them highly versatile. Mastery of dictionary operations like retrieving values, iterating over key-value pairs, and creating dictionaries from multiple sources is crucial for handling real-world datasets in data analysis.
Resources:
Day 4: Loops with Lists and Dictionaries
Introduction: Loops are fundamental constructs in Python that enable repetitive tasks, such as processing datasets or performing calculations. When working with data structures like lists and dictionaries, loops become indispensable for iterating over elements efficiently. Loops help automate and speed up data processing tasks in data analysis by allowing for quick transformations and aggregations of data.
Learning Objective: The objective of this lesson is to teach you how to use for and while loops to iterate over lists and dictionaries effectively. You will learn how to iterate through the elements of a list, access dictionary keys, values, and key-value pairs, and apply nested loops to process multi-dimensional data. By the end of the lesson, you should be able to combine loops with conditionals to manipulate data efficiently.
Scope of the Lesson: This lesson will cover the use of loops to iterate over lists and dictionaries. Specifically, you will explore iterating through lists using both index-based and item-based loops. You will also learn how to iterate over dictionary keys, values, and key-value pairs. Nested loops, which allow for iterating over more complex data structures like lists of dictionaries, will also be introduced. Additionally, you will learn how to combine loops with conditionals to filter or modify data based on certain criteria.
Background Information: In Python, lists can be iterated over using a for loop. You can either iterate directly over the list items with for item in my_list:, or iterate using an index with for i in range(len(my_list)):. The first method directly gives you the elements, while the second method gives you the index of each element. For dictionaries, you can iterate over the keys with for key in my_dict:, or use the dict.items() method to iterate over key-value pairs. To iterate over only the values in a dictionary, you can use dict.values(). Nested loops are useful for handling multi-dimensional data structures such as lists of lists or dictionaries of lists. In these cases, you may need a loop inside another loop to process each level of data. Additionally, you can combine loops with conditionals to filter data or perform specific actions. For example, using an if condition inside a loop allows you to filter out unwanted data or perform transformations based on certain criteria.
Examples to Practice:
# Example 1: Iterating over a list my_list = [1, 2, 3, 4, 5] for item in my_list: print(item) # Example 2: Iterating over a dictionary (keys) my_dict = {"name": "Alice", "age": 25} for key in my_dict: print(key) # Example 3: Iterating over a dictionary (key-value pairs) my_dict = {"name": "Alice", "age": 25} for key, value in my_dict.items(): print(f"{key}: {value}") # Example 4: Using a nested loop to iterate over a list of lists my_list_of_lists = [[1, 2, 3], [4, 5, 6]] for sublist in my_list_of_lists: for item in sublist: print(item) # Example 5: Using conditionals inside a loop to filter data my_list = [1, 2, 3, 4, 5] for item in my_list: if item % 2 == 0: print(f"Even number: {item}")
Explanation of the Example Codes & Outputs: In Example 1, the for loop iterates over the elements of my_list, printing each item. In Example 2, we iterate over the keys of my_dict, which prints each key (i.e., "name" and "age"). Example 3 demonstrates iterating over both the keys and values in my_dict using items(). This loop prints each key-value pair in the dictionary. Example 4 uses nested loops to process a list of lists (my_list_of_lists), printing all the elements within each sublist. In Example 5, a condition inside the loop checks if each item in my_list is even, and if so, prints it with a message.
Supplemental Information: Mastering loops with lists and dictionaries is essential for efficient data processing. Using for loops allows you to iterate over collections quickly, and combining them with conditionals enables more powerful data manipulation techniques. Nested loops extend this power to handle more complex data structures. The ability to iterate through and manipulate lists and dictionaries is foundational for data analysis tasks such as cleaning, transformation, and aggregation.
Resources:
Day 5: Practical Applications of Functions and Loops
Introduction: Combining functions with loops allows you to solve practical data analysis problems efficiently. These constructs are essential for automating tasks such as summarizing datasets, filtering records, or performing repetitive transformations. By encapsulating logic in functions and using loops for iteration, Python offers a highly efficient way to handle complex data workflows and automate data analysis processes.
Learning Objective: The objective of this lesson is to apply functions and loops in real-world data analysis tasks. You will learn how to write functions that perform specific tasks (e.g., calculating averages), use loops to process lists and dictionaries, and handle common edge cases, such as empty lists or missing data. The goal is to make data analysis workflows more efficient and scalable by leveraging the power of functions and loops.
Scope of the Lesson: This lesson will focus on writing Python functions for specific data analysis tasks, such as calculating averages, sums, or finding maximum/minimum values. Additionally, you will learn how to apply loops to process datasets, whether in lists or dictionaries. Special attention will be given to error handling and edge cases, which are crucial for building robust and reliable code. By the end of the lesson, you will be equipped with practical techniques to automate data processing tasks and manage common pitfalls in real-world datasets.
Background Information: Functions allow you to encapsulate logic, making code more modular and reusable. For example, a function could be written to calculate the average of a list of numbers. Loops, on the other hand, provide a way to iterate over data structures such as lists and dictionaries, applying the function to each element or group of elements. Combining these two tools, you can efficiently analyze large datasets by performing repetitive tasks, like summarizing statistics or transforming data. Practical applications of functions and loops include calculating sums, determining the maximum or minimum value in a dataset, filtering out irrelevant data, or performing data transformations. For example, you can write a function that computes the average of numbers in a list, and then use a loop to apply this function across different subsets of data. Additionally, error handling is important when working with real-world data, where issues like empty lists or missing values might arise. Anticipating these edge cases and handling them gracefully ensures that your code remains robust and reliable.
Examples to Practice:
# Example 1: Function to calculate average of a list def calc_avg(lst): if len(lst) == 0: return 0 # Handling edge case for empty list return sum(lst) / len(lst) print(calc_avg([1, 2, 3])) # Output: 2.0 # Example 2: Using a loop to calculate sum of values in a list my_list = [5, 10, 15, 20] total = 0 for num in my_list: total += num print(f"Total: {total}") # Output: Total: 50 # Example 3: Applying function to a list of lists (nested loop) list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] for sublist in list_of_lists: avg = calc_avg(sublist) print(f"Average of {sublist}: {avg}") # Example 4: Filtering out negative values using a function and loop def filter_negative(lst): return [num for num in lst if num >= 0] my_data = [5, -3, 7, -1, 8] filtered_data = filter_negative(my_data) print(f"Filtered Data: {filtered_data}") # Output: Filtered Data: [5, 7, 8]
Explanation of the Example Codes & Outputs: In Example 1, the calc_avg function computes the average of a list, with a check for an empty list to avoid division by zero. If the list is empty, it returns 0. Example 2 demonstrates a loop that iterates over my_list, summing its elements. Example 3 shows how the calc_avg function can be applied to each sublist within a list of lists. It calculates the average for each sublist using a nested loop. In Example 4, a list comprehension is used inside the filter_negative function to filter out negative values from a list. The output prints only non-negative values from the my_data list.
Supplemental Information: Combining functions and loops is a powerful technique for automating common data analysis tasks. By writing modular functions for specific tasks (like calculating averages or filtering data), you can reuse the logic across different datasets or parts of your code. Loops enable you to apply these functions to multiple elements, saving time and reducing redundancy. Additionally, error handling ensures that your code remains functional, even when faced with unexpected data issues like empty lists or missing values. Mastering these tools will make you much more efficient in handling large, complex datasets.
Resources:
Daily Quiz
Practice Lab
Select an environment to practice coding exercises.
Exercise
Download the following files to support your learning:
Grade
Day 1 Score: Not completed
Day 2 Score: Not completed
Day 3 Score: Not completed
Day 4 Score: Not completed
Day 5 Score: Not completed
Overall Average Score: Not calculated
Overall Grade: Not calculated
Generate Certificate
Click the button below to generate your certificate for completing the course.