Layer 1 Session 08 Python Foundations

Functions and Lambda

Every piece of logic we have written so far has been repeated inline. Functions let us name a piece of logic once and reuse it โ€” the basis for everything from here forward.

x f(x) result a function is just a labeled transformation

Logic, named once, reusable everywhere.

Estimated time: 35โ€“40 minutes  ยท  Pre-quiz โ†’ Concept โ†’ Lab โ†’ Commit โ†’ Post-quiz

1. Learning Objective

By the end of this session you will be able to:

  • Define a function with def, including default parameter values
  • Explain the difference between a parameter and an argument, and between positional and keyword arguments
  • Use return to send a value back to the caller, and understand a function with no return gives back None
  • Write a small lambda expression and know when it is (and is not) appropriate
  • Pass a function as an argument to sorted() using the key parameter

2. Pre-Coding Quiz

Answer these before reading the concept explanation or writing any code. It is fine to get these wrong โ€” that is the point. You need 4/5 to proceed to the lab.

Question 1 of 5

Given def greet(name):\n return f"Hello, {name}", what does greet("Kenya") evaluate to?

Calling the function substitutes the argument "Kenya" for the parameter name, and return sends the formatted string back to the caller.
Question 2 of 5

What does print(greet("Kenya")) print if greet uses print(f"Hello, {name}") instead of return?

The function itself prints "Hello, Kenya" as a side effect. But since it has no return, calling it evaluates to None โ€” and the outer print() then prints that None on the next line. This is a very common beginner confusion between printing and returning.
Question 3 of 5

Given def region_label(name, region="Unknown"):, what does region_label("Kenya") return for region?

A default parameter value is used whenever the caller does not supply that argument. This lets callers omit parameters they don't care about.
Question 4 of 5

Which lambda is equivalent to def get_pop(c): return c["population"]?

A lambda has no def, no name, no parentheses around parameters, and no return keyword โ€” the expression after the colon is implicitly returned.
Question 5 of 5

You call sorted(countries, key=lambda c: c["population"]). What does the key argument control?

sorted() normally compares items directly, which fails for dicts. key tells it: "for each item, run this function, and sort based on what it returns" โ€” here, each country's population.

3. The Concept โ€” Functions and Lambda

PRINT()side effect(console only)RETURNvalue flows backto the caller

print() sends text to the console; return sends a value back into the calling code so it can be used further.

Defining a function

A function packages up logic under a name so it can be called repeatedly instead of copy-pasted.

def greet(name):
    return f"Hello, {name}"

print(greet("Kenya"))  # "Hello, Kenya"
print(greet("Ghana"))  # "Hello, Ghana"

return vs print โ€” a critical distinction

print() displays something to the console as a side effect. return sends a value back to whoever called the function, so it can be stored, passed along, or used in another expression. A function with no return statement evaluates to None.

def broken_greet(name):
    print(f"Hello, {name}")   # side effect โ€” does NOT return anything

result = broken_greet("Kenya")   # prints "Hello, Kenya" as a side effect
print(result)                     # None โ€” nothing was returned

Default parameter values

A parameter can have a default, used whenever the caller omits that argument.

def region_label(name, region="Unknown"):
    return f"{name} ({region})"

print(region_label("Kenya", "Africa"))  # "Kenya (Africa)"
print(region_label("Atlantis"))          # "Atlantis (Unknown)" โ€” default used

Lambda โ€” a small, anonymous function

A lambda is a function expression with no name, written on one line, with the result implicitly returned. Lambdas are for short, throwaway logic โ€” usually passed straight into another function.

# Full function
def get_pop(c):
    return c["population"]

# Equivalent lambda
get_pop = lambda c: c["population"]

# Where lambdas actually shine: passed inline as an argument
countries = [
    {"name": "Kenya", "population": 54000000},
    {"name": "Ghana", "population": 31000000},
]
by_population = sorted(countries, key=lambda c: c["population"])
print([c["name"] for c in by_population])  # ['Ghana', 'Kenya']

When to use a full function instead of a lambda

If the logic needs a name for clarity, spans more than one line, or is reused in several places, write a real def function. A lambda is for a single, obvious, inline expression only.

# Bad: cramming multi-step logic into a lambda hurts readability
# label = lambda c: c["name"] + " (" + c["region"] + ")" if c.get("region") else c["name"]

# Good: a real function with a name says what it does
def format_label(c):
    if c.get("region"):
        return f"{c['name']} ({c['region']})"
    return c["name"]

4. Lab

Lab objective: Write reusable functions for formatting and sorting countries, including one lambda used with sorted().

What you will build

A file called functions_lab.py.

Step-by-step instructions

1

Create the file and the country list

# functions_lab.py
countries = [
    {"name": "Kenya", "region": "Africa", "population": 54000000},
    {"name": "Ghana", "region": "Africa", "population": 31000000},
    {"name": "Peru", "region": "Americas", "population": 33000000},
]
2

Write a function that formats one country as a label

Give region a default value of "Unknown".

def format_country(name, region="Unknown"):
    return f"{name} ({region})"

print(format_country("Kenya", "Africa"))
print(format_country("Atlantis"))  # uses the default
3

Write a function that returns the population, and one that prints it

Call both and print the results to see the return-vs-print difference for yourself.

def get_population(country):
    return country["population"]

def show_population(country):
    print(country["name"], "has population", country["population"])

result = show_population(countries[0])
print("show_population returned:", result)  # None
print("get_population returned:", get_population(countries[0]))
4

Sort countries by population using a lambda

by_population = sorted(countries, key=lambda c: c["population"])
for c in by_population:
    print(c["name"], c["population"])
5

Sort countries by population, descending

Look up the reverse parameter of sorted().

by_population_desc = sorted(countries, key=lambda c: c["population"], reverse=True)
print([c["name"] for c in by_population_desc])

5. Expected Files Changed

FileActionWhy
functions_lab.py Created Demonstrates function definitions, defaults, return vs print, and lambda with sorted().
docs/sessions/session-08/index.html Created This session document.
If you find yourself editing any other file, stop. This session touches exactly 2 files.

6. Commit Checkpoint

Once the lab is complete and you can explain every line, make this exact commit:

git add functions_lab.py docs/sessions/session-08/index.html
git commit -m "session-08: define reusable functions and sort with a lambda key"
Do not commit until you can answer out loud: "Why did show_population() print the value but return None, and why does that matter?"

7. Code Review Checklist

Go through your code line by line and check each item:


8. Post-Coding Quiz

Same 5 questions. Take it again now that you have written and run the code. You need 4/5 to mark this session complete.

Question 1 of 5

Given def greet(name):\n return f"Hello, {name}", what does greet("Kenya") evaluate to?

Calling the function substitutes the argument "Kenya" for the parameter name, and return sends the formatted string back to the caller.
Question 2 of 5

What does print(greet("Kenya")) print if greet uses print(f"Hello, {name}") instead of return?

The function itself prints "Hello, Kenya" as a side effect. But since it has no return, calling it evaluates to None โ€” and the outer print() then prints that None on the next line. This is a very common beginner confusion between printing and returning.
Question 3 of 5

Given def region_label(name, region="Unknown"):, what does region_label("Kenya") return for region?

A default parameter value is used whenever the caller does not supply that argument. This lets callers omit parameters they don't care about.
Question 4 of 5

Which lambda is equivalent to def get_pop(c): return c["population"]?

A lambda has no def, no name, no parentheses around parameters, and no return keyword โ€” the expression after the colon is implicitly returned.
Question 5 of 5

You call sorted(countries, key=lambda c: c["population"]). What does the key argument control?

sorted() normally compares items directly, which fails for dicts. key tells it: "for each item, run this function, and sort based on what it returns" โ€” here, each country's population.

9. Reflection Questions

Think through these after the post-quiz. No right answer โ€” they are for discussion.

  1. Why does Python separate "produce a value" (return) from "display a value" (print) instead of combining them?
  2. Rewrite the lambda c: c["population"] from the lab as a full def function. Which version is more readable in context?
  3. What would happen if you forgot the return keyword inside get_population? Try it and observe.
  4. Can you think of a case in the project ahead where a default parameter value would prevent a bug?

10. What Breaks If This Knowledge Is Missing?

  • The forgotten-return bug: Forgetting return is one of the most common beginner mistakes. The function appears to work (it prints correctly) but every caller that tries to use its result gets None instead โ€” a bug that only shows up downstream.
  • Data-layer functions (Layer 4): Session 28 builds a data-access layer entirely out of functions like the ones in this lab. If return values are not understood, that entire layer will silently pass None around.
  • Sorting and filtering UI logic: Nearly every "sort by X" or "filter by Y" feature in real software is built on exactly the key=lambda pattern from this session.

11. What We Learned

Python concept mastered: Functions โ€” def, parameters, defaults, return vs print, and lambda expressions used as sort keys.

Unlocks: You can now name and reuse logic instead of repeating it, and pass small functions as arguments to other functions.

Next session: Session 09 โ€” Unpacking and *args/**kwargs. We will learn to unpack values out of lists and dicts in one line, and accept flexible numbers of arguments with *args and **kwargs.