11  Appendix A: Fundamentals of Python Programming

An introduction to essential Python fundamentals required to understand the code in Chapters 1-6. This appendix assumes no prior programming experience and covers the core language features needed before engaging with scientific computing libraries.


11.1 Part 1: Basic Data Types and Printing

Before working with collections or control flow, you need to understand Python’s two most fundamental data types — integers and strings — and how to display them using print(). These building blocks appear in virtually every Python program.


11.1.1 Integers

An integer (int) is a whole number with no decimal point. Python handles integers of any size without special configuration.

How the code works: - Assigning any whole number to a variable automatically makes it an int - Arithmetic operators (+, -, *, //, %, **) all work on integers - type() returns the data type of any variable — useful when debugging


11.1.2 Strings

A string (str) is a sequence of characters enclosed in single or double quotes. Strings hold text, labels, file paths, and any other non-numeric data.

How the code works: - Single quotes '...' and double quotes "..." are interchangeable - len() returns the number of characters in the string - isinstance(value, type) checks whether a variable belongs to a given type


11.1.3 Printing Variables with Strings: the f-string

The cleanest way to combine variables and text inside a print() statement is the f-string (formatted string literal). Prefix the opening quote with f and wrap any variable or expression in curly braces {}:

How the code works: - The f prefix activates expression evaluation inside {...} - Any valid Python expression can go inside the braces: variables, arithmetic, function calls - Format specifiers after : control display — :.1f means one decimal place for a float - f-strings are far more readable than string concatenation with +


Quiz: Integer and String Types

What does the following code print?

x = 42
label = "answer"
print(type(x) == int, type(label) == str)






Quiz: f-string Output

What is the output of this code?

city = "Paris"
year = 2024
print(f"{city} hosted the Olympics in {year - 4}.")






Code Challenge Quiz: f-strings

Using the variables already defined, write a print() statement using an f-string so the output is exactly:

My name is Jordan and I am 22 years old.

When you’re done, click Run Code to check your answer.


11.2 Part 2: Core Python Data Structures

11.2.1 Understanding Python Data Types

Python has several built-in data types that allow you to store and organize information in different ways. Understanding when to use each data type is crucial for writing effective code.

Video Resource: Watch this overview of Python’s data types: Python Data Types on YouTube

Overview of Python Data Types:

Python organizes data types into several categories:

  1. Numeric Types: int (integers like 5, -10), float (decimals like 3.14), complex (numbers with imaginary parts)
  2. Sequence Types: list (ordered, mutable), tuple (ordered, immutable), str (text)
  3. Mapping Type: dict (key-value pairs, unordered but organized by keys)
  4. Set Types: set (unordered, unique elements), frozenset (immutable set)
  5. Boolean Type: bool (True or False)

Each data type serves a specific purpose. Lists are great for collections you want to modify. Tuples are perfect for fixed-size collections. Dictionaries organize information by meaningful keys. Sets are useful for removing duplicates or checking membership. Understanding which to use makes your code cleaner and more efficient.


11.2.2 Lists

A list is an ordered collection of items that can be of any type. Lists are mutable, meaning you can change, add, or remove items after creating them.

Creating and Accessing Lists

How the code works: - We create lists using square brackets [...] with items separated by commas - We access individual items using indexing with square brackets: list[index] - Python uses zero-based indexing, meaning the first element is at index 0


Quiz: Creating and Accessing Lists

What is the output of this code?

fruits = ["apple", "banana", "cherry"]
print(fruits[1])





Negative Indexing and Slicing

How the code works: - Negative indices count backward: -1 is the last element, -2 is second-to-last - Slicing uses the syntax [start:stop:step] - The stop index is exclusive (not included in the result) - Omitting start, stop, or step uses defaults (beginning, end, or 1)


Quiz: Negative Indexing and Slicing

What does numbers[-2:] return from the list [10, 20, 30, 40, 50]?





List Methods

How the code works: - Each method performs a specific operation on the list - append() and extend() add items (one item vs. multiple items) - insert() adds at a specific position - remove() removes by value, pop() removes by index - index() finds where a value is located


Quiz: List Methods

After running this code, what is the value of colors?

colors = ["red", "green"]
colors.append("blue")
colors.extend(["yellow"])





List Comprehension

How the code works: - List comprehension creates a new list in a single line - Syntax: [expression for item in iterable] - Can add conditions: [expression for item in iterable if condition] - More concise and often faster than loops

Iterating Through Lists

How the code works: - for item in list: iterates through each item - enumerate() provides both the index and value - The variable after for is assigned each item in turn —

Quiz: Creating and Accessing Lists

What is the output of this code?

fruits = ["apple", "banana", "cherry"]
print(fruits[1])






Quiz: Lists

What is the key characteristic of lists in Python?






11.2.3 Tuples

A tuple is an ordered collection like a list, but it is immutable—once created, you cannot change its contents.

Creating and Using Tuples

How the code works: - Tuples use parentheses (...) instead of square brackets - Single-item tuples need a trailing comma (42,) to distinguish from parentheses - Indexing and slicing work exactly like lists

Tuple Immutability

How the code works: - Attempting to modify a tuple raises a TypeError - This immutability is useful for protecting data that shouldn’t change


Quiz: Tuple Immutability

What happens when you try to run this code?

coords = (10, 20)
coords[0] = 15





Tuple Unpacking

How the code works: - Unpacking assigns each element of a tuple to a variable - The number of variables must match the number of elements - Parentheses can be omitted: x, y = coordinates works the same


Quiz: Tuples

What happens when you try to modify a tuple?






11.2.4 Dictionaries

A dictionary stores key-value pairs, where you access values by their keys rather than by index.

Creating and Accessing Dictionaries

How the code works: - Dictionaries use curly braces {key: value, ...} - Access values with dict[key] using square brackets - The .get() method is safer—it returns a default value if the key doesn’t exist

Modifying Dictionaries

How the code works: - Assign to a key to add or modify: dict[key] = value - Use del to remove a key-value pair - Use in to check if a key exists


Quiz: Dictionary Key-Value Access

What does this code print?

student = {"name": "Alice", "age": 20, "grade": "A"}
print(student["age"])





Iterating Through Dictionaries

How the code works: - Iterating over a dictionary by default gives you keys - .items() gives you both keys and values as tuples - .keys() and .values() return the keys and values separately


Quiz: Dictionaries

What is the primary advantage of using dictionaries?






11.2.5 Sets

A set is an unordered collection of unique items. Sets are useful for removing duplicates and performing set operations.

Creating and Using Sets

How the code works: - Sets use curly braces {...} but without key-value pairs - Duplicate values are automatically removed - Creating a set from a list is a quick way to remove duplicates

Set Operations

How the code works: - in operator checks if an element exists in the set - | performs union (all elements) - & performs intersection (common elements) - - performs difference (elements only in first set)


Quiz: Sets

What are the two defining characteristics of sets?






11.3 Part 3: Control Flow and Conditionals

Video Resource: Watch this visual explanation of Python booleans and conditionals: Python Booleans and Conditionals - Visually Explained

11.3.1 Conditional Statements

Conditional statements allow your code to make decisions based on conditions.

If, Elif, Else

How the code works: - if condition: executes if the condition is true - elif condition: (else-if) checks another condition if the first is false - else: executes if none of the previous conditions are true - Conditions are indented (usually 4 spaces)

Comparison and Logical Operators

How the code works: - Comparison operators return True or False - and: both conditions must be true - or: at least one condition must be true - not: inverts the condition

Membership Testing

How the code works: - in checks if an item exists in a collection - not in checks if an item does NOT exist


Quiz: Control Flow and Conditionals

What is the output of this code?

age = 16
if age >= 18:
    print("You are an adult")
else:
    print("You are a minor")






11.3.2 Loops

A loop repeats a block of code multiple times. Python has two loop types: for loops (repeat over a known sequence) and while loops (repeat as long as a condition is true).


for Loops

A for loop iterates over any sequence — a range of numbers, a list, or any other collection. Each iteration assigns the next item to the loop variable.

How the code works: - range(5) produces the integers 0, 1, 2, 3, 4 — the loop variable i takes each value in turn - Iterating a list assigns each element in order to the loop variable - enumerate() yields (index, value) pairs — useful when you need both the position and the item


while Loops

A while loop keeps running as long as its condition remains True. Use it when you don’t know in advance how many iterations are needed.

How the code works: - The condition count > 0 is checked before each iteration; when it becomes False the loop stops - The count -= 1 line is essential — without it the loop would run forever (infinite loop) - The second loop uses and to stop on whichever condition triggers first


Loop Control: break, continue, pass

Three keywords let you alter a loop’s normal execution:

How the code works: - break exits the entire loop as soon as the condition is met - continue jumps straight to the next iteration, skipping any remaining code in the current one - pass is a no-op — Python requires at least one statement in a block; pass fills that role


Quiz: Loops

What does the following code print?

for i in range(3):
    if i == 1:
        continue
    print(i)






Code Challenge Quiz: For Loops

The list numbers is already defined. Write a for loop that prints each number multiplied by 2 so the output is exactly:

2
4
6
8
10

When you’re done, click Run Code to check your answer.


11.4 Part 4: Functions

Video Resource: Watch this visual explanation of Python functions: Python Functions - Visually Explained

11.4.1 Defining and Calling Functions

Functions allow you to write reusable blocks of code.

Basic Function Definition

How the code works: - def function_name(parameters): defines a function - Parameters are variables that receive values when called - Indented code is the function body - Call a function by using its name with parentheses and arguments


Quiz: Functions

What does this code print?

def add(x, y):
    return x + y

print(add(5, 3))






11.4.2 Return Values

Functions can return values to the calling code.

Returning Single and Multiple Values

How the code works: - return value sends a value back to where the function was called - Multiple values separated by commas are returned as a tuple - Returned values can be assigned to variables - Functions without a return statement return None


Quiz: Return Values

What does this code print?

def get_sum(a, b):
    total = a + b
    return total

result = get_sum(3, 4)
print(result)






11.4.3 Function Parameters

Functions can have different types of parameters.

Positional and Default Parameters

How the code works: - Positional parameters must be provided in the same order - Default parameters have a default value if not provided - You can override a default by providing a value

Keyword Arguments

How the code works: - Keyword arguments use parameter=value syntax - Keyword arguments can be in any order - All positional arguments must come before keyword arguments


Quiz: Function Parameters

What does this code print?

def greet(name, greeting="Hello"):
    print(f"{greeting}, {name}!")

greet("Alice")
greet("Bob", "Hi")






11.4.4 Variable Scope

Understanding where variables exist and can be accessed is important.

Local and Global Variables

How the code works: - Global variables are defined outside all functions - Local variables are defined inside a function - Local variables only exist while the function is running - Each function has its own local scope


Quiz: Variable Scope

What does this code print?

x = 10

def my_function():
    x = 20
    print(x)

my_function()
print(x)





The Global Keyword (Use Sparingly)

How the code works: - The global keyword lets you modify a global variable from inside a function - This can make code hard to understand; usually avoid it - Better to pass values as parameters and return new values


11.4.5 Documentation and Clarity

Good code includes documentation and uses clear naming.

Docstrings and Comments

How the code works: - Docstrings (triple-quoted strings) document what a function does - Comments (lines starting with #) explain why code does something - Type hints can be added (shown next)


Quiz: Documentation and Clarity

What is the purpose of a docstring?

def calculate_area(radius):
    """Calculate the area of a circle."""
    return 3.14159 * radius ** 2





Type Hints

How the code works: - Type hints use the syntax parameter: type and -> return_type - They document what types are expected - Python doesn’t enforce them; they’re helpful for code clarity


11.4.6 Lambda Functions

Lambda functions are small, anonymous functions useful for simple operations.

Creating and Using Lambda Functions

How the code works: - Lambda syntax: lambda parameters: expression - Lambdas return the value of the expression - Useful for simple, one-time-use functions


Quiz: Lambda Functions

What is the output of this code?

square = lambda x: x ** 2
print(square(5))





Lambda with Map and Filter

How the code works: - map() applies a function to each item and returns results - filter() keeps items where the function returns True - List comprehensions often accomplish the same thing more clearly


11.5 Part 5: String Operations and Formatting

Video Resource: Watch this visual explanation of Python strings: Python Strings - Visually Explained

11.5.1 String Basics

Strings are sequences of characters.

Creating and Basic Operations

How the code works: - Strings can use single or double quotes - Triple quotes allow multi-line strings - + concatenates (joins) strings - * repeats a string


Quiz: String Basics

What is the output of this code?

text = "hello"
print(text[1])





String Methods

How the code works: - String methods don’t modify the original (strings are immutable) - They return a new string with the changes - split() breaks a string into a list - join() combines a list into a string - Methods are called with a dot: string.method()


Quiz: Strings

What is special about the string text = "hello"?






11.5.2 String Formatting for Output

There are several ways to format strings in Python.

F-strings (Modern Approach)

How the code works: - F-strings use f"..." prefix - {expression} evaluates the expression - {value:.2f} formats a float with 2 decimal places - {value:10s} right-aligns a string in 10 characters - {value:3d} formats an integer in at least 3 characters


Quiz: String Formatting for Output

What does this code print?

name = "Alice"
age = 25
print(f"Name: {name}, Age: {age}")





The .format() Method

How the code works: - {} is a placeholder - .format() fills in the placeholders - Can use positional or named arguments

Basic Print Usage

How the code works: - print() separates items with spaces by default - sep="" parameter changes the separator - end="" parameter changes the ending character


11.5.3 Practical Examples

Real-world string formatting examples.

How the code works: - < left-aligns, > right-aligns within a field width - Useful for creating tabular output - Error messages with formatted values are more helpful


Quiz: Practical String Formatting Examples

What is the output?

value = 3.14159
print(f"Pi = {value:.2f}")






11.6 Part 6: Exception Handling

11.6.1 Understanding Exception Handling

Exception handling is a critical skill for writing robust Python code. Rather than allowing your program to crash when an error occurs, exception handling lets you detect, respond to, and recover from errors gracefully.

Video Resource: Watch this comprehensive introduction to exception handling: Python Exception Handling on YouTube

The Purpose of Exception Handling:

Exception handling serves several critical purposes in software development:

  1. Prevents Program Crashes: Without exception handling, a single error (like dividing by zero or accessing a non-existent file) crashes your entire program. Exception handling lets you catch these errors and handle them gracefully.

  2. Provides User-Friendly Error Messages: Instead of cryptic system errors, you can provide clear, helpful messages explaining what went wrong and how to fix it.

  3. Enables Recovery and Fallback Logic: When an error occurs, you can execute alternative code. For example, if a file can’t be opened, you might create a default file or use a default dataset.

  4. Logs and Monitors Errors: In larger applications, exception handling lets you log what went wrong for debugging and analysis, helping you improve your code over time.

  5. Ensures Resource Cleanup: The finally block guarantees that cleanup code (like closing files or releasing memory) runs even when errors occur, preventing resource leaks.

In video terms: the try block is your “attempt,” the except block is your “safety net,” and the finally block is your “cleanup crew.” Together, they keep your program running smoothly even when things go wrong.


11.6.2 Basic Exception Handling

Exceptions allow graceful handling of errors.

Try-Except-Finally Structure

How the code works: - try: contains code that might raise an exception - except ExceptionType: handles a specific exception type - finally: runs regardless of whether an exception occurred - Multiple except blocks handle different exception types


11.6.3 Common Exceptions

Understanding common Python exceptions.

How the code works: - Each exception type indicates a different kind of error - Catching specific exceptions allows targeted error handling - Understanding exception types helps you write better error messages


11.6.4 Raising Exceptions

You can raise exceptions in your own code.

How the code works: - raise ExceptionType("message") raises an exception - Useful for input validation - The as e syntax captures the exception object - The exception message provides useful context


11.6.5 Practical Use Cases

Real-world exception handling patterns.

How the code works: - Input validation prevents invalid data from causing problems - Error messages help users understand what went wrong - Graceful error handling allows programs to continue running


Quiz: Exception Handling Practical Use

What does this code print?

def safe_divide(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        return None

result = safe_divide(10, 0)
print(result)






11.6.6 5.5 Quiz: Test Your Understanding of Exception Handling

Quiz: Understanding Try-Except-Finally

What happens when this code runs?

try:
    value = int("abc")
    result = 100
except ValueError:
    print("Error: Cannot convert to integer")
    result = None
finally:
    print("Done")






Quiz: Understanding When Finally Runs

What gets printed when this code runs?

try:
    file = open("nonexistent.txt", "r")
except FileNotFoundError:
    print("Error: File not found")
finally:
    print("Cleanup complete")






11.7 Part 7: Debugging and Problem-Solving

11.7.1 Debugging Techniques

Finding and fixing bugs in your code.

Using Assertions

How the code works: - assert condition, "message" stops execution if condition is false - Useful for catching bugs during development - Shouldn’t be used for user input validation (use exceptions instead)

Checking Variable Types and Values

How the code works: - type() returns the data type - isinstance() checks if something is a specific type - hasattr() checks if an object has an attribute - These help understand what went wrong


11.7.2 Common Errors and How to Fix Them

Recognizing and fixing common mistakes.

How the code works: - Each error type points to a specific problem - Understanding the error message helps you find the fix - Using defensive programming (checking before accessing) prevents errors


11.7.3 Reading Error Messages

Error messages tell you what went wrong and where.

How the code works: - Error messages have three main parts: type, message, and location - The traceback shows the function call stack - Use this information to identify and fix the bug


Quiz: Debugging Techniques

Which is the best approach to debug code?






11.8 Part 8: Object-Oriented Programming (OOP) Basics

11.8.1 Classes and Objects: Introduction

Classes are blueprints for creating objects.

Creating a Simple Class

How the code works: - class ClassName: defines a class - __init__ is the constructor, called when creating an object - self refers to the specific object being created - Each object has its own attributes (name, age)


11.8.2 Attributes and Methods

Objects contain data (attributes) and functions (methods).

Adding Methods to a Class

How the code works: - Methods are functions defined inside a class - self.attribute accesses the object’s data - Methods can modify the object’s state - Call methods with object.method()


Quiz: Attributes and Methods

What is the difference between an attribute and a method?






11.8.3 Toy Example: Animal Class

A more complete example showing OOP concepts.

Complete Animal Class Example

How the code works: - __init__ initializes all attributes - describe() returns information about the animal - have_birthday() modifies the age attribute - make_sound() is a method that can be customized


11.8.4 Instance vs. Class Level

Understanding the difference between instance and class attributes.

How the code works: - Class attributes are defined outside __init__ and shared by all instances - Instance attributes are defined in __init__ and unique to each object - Class attributes are accessed with ClassName.attribute - Instance attributes are accessed with self.attribute


Quiz: Object-Oriented Programming

What is the output of this code?

class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def have_birthday(self):
        self.age += 1
        return f"{self.name} is now {self.age}"
    
    def describe(self):
        return f"{self.name} is a {self.age}-year-old dog"

my_dog = Dog("Buddy", 3)
print(my_dog.have_birthday())
print(my_dog.describe())






11.8.5 When to Use Classes

Understanding when OOP is useful.

How the code works: - Use classes when you have data and related operations - Classes help manage state (data that changes) - Don’t overuse classes; simple functions are fine for simple tasks - Classes become more valuable as complexity increases


11.9 Part 8: Import Statements

11.9.1 Basic Imports

Importing and using modules.

How the code works: - import module imports the entire module - from module import function imports specific items - import module as alias creates a shorter name - Accessed with module.function() or directly if imported with from


Quiz: Basic Imports

What is the output of this code?

import math
print(math.sqrt(16))






11.9.2 Using Imported Modules

Understanding what modules contain.

How the code works: - dir(module) shows what’s available in a module - help(function) shows documentation - These tools help you learn what a module offers


Quiz: Imports and Modules

What is the difference between these two approaches?

# Approach 1
import math
result = math.sqrt(16)

# Approach 2
from math import sqrt
result = sqrt(16)






11.9.3 Organizing Imports

Best practices for importing.

How the code works: - Group imports by type: standard library, third-party, local - This organization makes code readable - Helps identify dependencies at a glance


11.10 Exercises

11.10.1 Part 1: Data Structures

List Exercises

Exercise 1.1.1: List Indexing and Slicing

Exercise 1.1.2: List Methods


Tuple Exercises

Exercise 1.2.1: Tuple Unpacking

Exercise 1.2.2: Using Tuples in Functions


Dictionary Exercises

Exercise 1.3.1: Dictionary Operations

Exercise 1.3.2: Iterating Dictionaries


11.10.2 Part 2: Control Flow

Conditional Exercises

Exercise 2.1.1: If-Elif-Else

Exercise 2.1.2: Logical Operators


Loop Exercises

Exercise 2.2.1: For Loops with Range

Exercise 2.2.2: Loop with Enumerate


11.10.3 Part 3: Functions

Function Definition Exercises

Exercise 3.1.1: Basic Functions

Exercise 3.1.2: Functions with Default Parameters


Return Value Exercises

Exercise 3.2.1: Multiple Return Values

Exercise 3.2.2: Conditional Returns


11.10.4 Part 4: String Operations

String Formatting Exercises

Exercise 4.2.1: F-String Formatting

Exercise 4.2.2: String Methods


11.10.5 Part 5: Exception Handling

Try-Except Exercises

Exercise 5.1.1: Handling Multiple Exceptions

Exercise 5.1.2: Input Validation


11.10.6 Part 6: Debugging

Debugging Exercises

Exercise 6.1.1: Finding and Fixing Bugs

Here’s buggy code - find and fix the errors:

def calculate_average(numbers):
    total = 0
    for num in numbers:       # FIXED: Added colon
        total = total + num
    return total / len(numbers)

Should calculate average of [10, 20, 30] = 20 Find the bug(s) and fix them

Exercise 6.1.2: Using Assertions


11.10.7 Part 7: Object-Oriented Programming

Class Exercises

Exercise 7.1.1: Creating a Simple Class

Exercise 7.1.2: Classes with State Management



11.11 Summary of Key Concepts

After completing this appendix, you should understand:

  • Data Structures: How to create and manipulate lists, tuples, dictionaries, and sets
  • Control Flow: How to make decisions with if/elif/else and repeat code with loops
  • Functions: How to write reusable code with parameters and return values
  • Strings: How to create, manipulate, and format text output
  • Error Handling: How to gracefully handle errors with try/except
  • Debugging: How to find and fix bugs in your code
  • OOP Basics: How to organize data and functions into classes
  • Imports: How to use code from modules and libraries

These fundamentals provide the foundation for the code in Chapters 1-6, where you’ll apply these concepts to scientific computing with NumPy, image processing, and data analysis.

Sign in to save progress

0 / 0

📚 Gradebook

Loading…

Sign in to save progress