Python Foundations: Intermediate

Every December, Spotify Wrapped turns raw streaming data into the personalized year-in-review cards that hundreds of millions of users share across social media, and Python string formatting and type conversion sit at the heart of that pipeline. Spotify's data engineers take billions of integer play counts, convert them into formatted strings, and embed them inside precisely worded messages using f-strings and type conversion functions. A raw count like 847293 becomes "You listened to this song 847,293 times" only because someone wrote exactly the kind of type conversion and string formatting code you are about to practice. The techniques in this lesson are what let Spotify transform a database full of numbers into the viral, personalized stories their users look forward to every year.

Conditional Statements

Daily Life
Interviews

Make your code choose between paths

Programs need to make decisions based on data. Conditional statements let your code choose different paths depending on whether conditions are met.

The If/Elif/Else Structure

The if/elif/else structure evaluates conditions in order and executes the first block where the condition is True. If no conditions match, the else block runs.

1age = 15
2if age >= 18:
3 print("Adult")
4elif age >= 13:
5 print("Teen")
6else:
7 print("Child")
>>>Output
Teen
Fill in the Blank

> A student scored 75 on a test. Pick the right comparison operator to check if they earned a passing grade (60 or above).

score = 75
if score  60:
    print("Pass")
else:
    print("Fail")
Each keyword plays a distinct role in the conditional chain. Understanding when to use each one is key to writing clear branching logic.
ifelifelse
if
First check
Entry point for the chain
elif
Extra checks
Additional branch options
else
Default branch
Catches all other cases

Python does not have a switch or case statement like some other languages. Instead, a chain of elif clauses handles multiple discrete conditions cleanly.

Python Quiz

> Classify a person as an adult or minor based on their age. Choose the keyword that checks a condition once, and the keyword that handles the default case.

age = 20
___ age >= 18:
    status = "adult"
___:
    status = "minor"
print(status)
for
else
if
elif
while

Conditions can be combined using the and, or, and not operators. A compound condition like age >= 18 and has_id must be True on both sides to pass.

Python evaluates conditions using short-circuit logic. In an and expression, if the first condition is False, Python skips evaluating the second one entirely.

Ternary expressions provide a single-line alternative for simple if/else assignments. The form value_if_true if condition else value_if_false is concise and readable.

Loops

Daily Life
Interviews

Repeat actions across collections of data

Loops let you repeat code without writing it multiple times. Python provides two main loop types, each suited to different situations.

For Loops

for loops iterate over sequences like lists, strings, or ranges. They automatically handle the iteration, making them ideal when you know what to iterate over.

1for i in range(5):
2 print(i)
>>>Output
0
1
2
3
4

While Loops

while loops continue executing as long as a condition remains True. Use break to exit early and continue to skip to the next iteration.

1count = 0
2while count < 5:
3 print(count)
4 count += 1
>>>Output
0
1
2
3
4
Choosing the right loop type makes your code clearer. Each loop type has a natural use case where it shines.
Debug Challenge

> This for loop should print numbers 0 through 4, but it has a syntax error. Find and fix it.

SyntaxError: expected a colon after the for statement

for: known iterations
for: known iterations
Best when you know the sequence or range to iterate over
while: condition-based
while: condition-based
Best when you loop until a condition changes to False
break and continue
break and continue
Control loop flow by exiting early or skipping iterations

The enumerate() function pairs each item with its index as you loop, eliminating the need to manually track a counter variable alongside the loop variable.

Functions

Daily Life
Interviews

Package reusable logic into functions

Functions let you package code into reusable units. Instead of repeating the same logic, you define it once and call it whenever needed.

Defining Functions

Use def followed by a name and parentheses to define a function. Parameters inside the parentheses accept input values.

//

Steps to Define a Function

Building a function follows a consistent pattern. Each step adds a layer of clarity to how the function works.
Fill in the Blank

> You want to create a reusable function that greets someone by name. Pick the correct keyword to define it.

 greet(name):
    print("Hello " + name)

greet("Alice")
01
Use def keyword
Start with def followed by the function name
02
Add parameters
List input variables inside the parentheses
03
Write the body
Indent the logic that executes when the function is called
04
Return a result
Use return to send the computed value back to the caller
Parameters are the variable names in the function definition. Arguments are the actual values you pass when calling the function.
1def calculate_total(price, tax_rate):
2 total = price * (1 + tax_rate)
3 return total
4
5result = calculate_total(100, 0.08)
6print(result)
>>>Output
108.0
Python Quiz

> Build a function that takes a name and sends back a greeting. Choose the keyword that sends a value back to the caller, and the parameter that holds the passed argument.

def greet(name):
    ___ "Hello, " + ___
message = greet("Alice")
print(message)
message
def
print
name
return

Default parameter values let callers omit arguments that have sensible defaults. Define them in the function signature with an equals sign, such as def greet(name="World").

Keyword arguments allow callers to pass values by name, making function calls self-documenting and removing the need to remember argument order.
Functions are first-class objects in Python. You can assign them to variables, pass them as arguments to other functions, and return them from other functions.

Return Values

Daily Life
Interviews

Get results back from your functions

Functions do more than just execute code. They can compute results and send them back to wherever they were called.

Returning Data

Use return to send a value back to the caller. A function can return any type of value. Without a return statement, a function returns None by default.

//

Multiple Return Values

Python functions can return multiple values as a tuple, which you can unpack into separate variables when calling the function.
1def divide(a, b):
2 if b == 0:
3 return None
4 return a / b
5
6print(divide(10, 3))
7print(divide(10, 0))
>>>Output
3.3333333333333335
None
Functions can also return multiple values as a tuple, which you can unpack into separate variables.
1def min_max(numbers):
2 return min(numbers), max(numbers)
3
4low, high = min_max([3, 1, 7, 2, 9])
5print(f"Min: {low}, Max: {high}")
>>>Output
Min: 1, Max: 9
Debug Challenge

> This function should double a number and return the result, but the caller gets None instead. Fix the function.

The function prints 10 but value is None because nothing is returned

A return statement immediately exits the function, so any code written after return in the same block is unreachable and will never execute.
Returning None explicitly and implicitly are equivalent. Both signal that the function completed without producing a meaningful value for the caller.
Functions that return multiple values as a tuple are a common Python pattern for situations where two related results, such as a minimum and maximum, are always needed together.

Variable Scope

Daily Life
Interviews

Control where variables are accessible

Scope controls where variables can be read and modified. Understanding scope prevents bugs and helps you write cleaner code.

Local vs Global Variables

Variables defined inside a function are local and exist only during that function call. Variables defined outside functions are global and accessible throughout your code.

//

The Global Keyword

Use the global keyword inside a function to modify a global variable. Without it, assignment creates a new local variable instead.

1count = 0
2
3def increment():
4 global count
5 count += 1
6
7increment()
8increment()
9print(count)
>>>Output
2

Without the global keyword, Python would create a new local variable instead of modifying the outer one. This is a common source of confusion.

SCOPE RULES (LEGB)
  • Local - variables defined inside the current function
  • Enclosing - variables in outer (enclosing) functions
  • Global - variables defined at the module level
  • Built-in - names pre-defined by Python (print, len, etc.)
Scope-related bugs are among the most common in Python. Following these guidelines keeps your variable management predictable.
Fill in the Blank

> A function needs to modify a variable defined outside of it. Pick the keyword that makes this possible.

x = 10

def change_x():
     x
    x = 20

change_x()
print(x)
Do
  • Use local variables by default
  • Pass values as function parameters
  • Return results instead of modifying globals
Don't
  • Overuse the global keyword
  • Rely on side effects for state
  • Shadow built-in names like list or str
One pattern in particular signals that your code might benefit from restructuring.
TIP
If you find yourself using global frequently, consider restructuring your code. Functions that take inputs and return outputs are easier to test and debug.
PUTTING IT ALL TOGETHER

> You are a data engineer at FedEx building a Python utility that validates incoming shipment records and routes each one to the correct warehouse queue before database insertion. The script must branch on record status, iterate every record, encapsulate validation logic, pass results back to the caller, and keep queue counters isolated per run.

Conditional statements route each shipment with if/elif/else so damaged, delayed, and normal records each reach the correct queue.
Loops iterate over the full batch with for record in shipments so every incoming row is validated without manual index management.
Functions encapsulate the validation logic as def validate(record) so the same rules apply consistently across all callers.
return values pass the cleaned record back to the caller, and variable scope keeps per-run counters like valid_count local to each invocation.
KEY TAKEAWAYS
if/elif/else statements control program flow based on conditions
for loops iterate over sequences; while loops run until False
Functions encapsulate reusable code with parameters and return values
Variable scope determines where variables are accessible

Decisions, loops, and reusable logic

Category
Python
Difficulty
intermediate
Duration
20 minutes
Challenges
0 hands-on challenges

Topics covered: Conditional Statements, Loops, Functions, Return Values, Variable Scope

Lesson Sections

  1. Conditional Statements

    Programs need to make decisions based on data. Conditional statements let your code choose different paths depending on whether conditions are met. The If/Elif/Else Structure Each keyword plays a distinct role in the conditional chain. Understanding when to use each one is key to writing clear branching logic.

  2. Loops

    Loops let you repeat code without writing it multiple times. Python provides two main loop types, each suited to different situations. For Loops While Loops Choosing the right loop type makes your code clearer. Each loop type has a natural use case where it shines.

  3. Functions

    Functions let you package code into reusable units. Instead of repeating the same logic, you define it once and call it whenever needed. Defining Functions Steps to Define a Function Building a function follows a consistent pattern. Each step adds a layer of clarity to how the function works. Parameters are the variable names in the function definition. Arguments are the actual values you pass when calling the function. Keyword arguments allow callers to pass values by name, making function call

  4. Return Values

    Functions do more than just execute code. They can compute results and send them back to wherever they were called. Returning Data Multiple Return Values Python functions can return multiple values as a tuple, which you can unpack into separate variables when calling the function. Functions can also return multiple values as a tuple, which you can unpack into separate variables. A return statement immediately exits the function, so any code written after return in the same block is unreachable a

  5. Variable Scope

    Scope controls where variables can be read and modified. Understanding scope prevents bugs and helps you write cleaner code. Local vs Global Variables The Global Keyword Scope-related bugs are among the most common in Python. Following these guidelines keeps your variable management predictable. One pattern in particular signals that your code might benefit from restructuring.