Get AI summaries of any video or article — Sign up free
Python Tutorial for Beginners 8: Functions thumbnail

Python Tutorial for Beginners 8: Functions

Corey Schafer·
5 min read

Based on Corey Schafer's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.

TL;DR

Define functions with `def` and use parentheses to execute them; parentheses are what trigger the function’s code.

Briefing

Functions in Python are reusable blocks of instructions defined with `def` that can take inputs (parameters) and optionally produce outputs (return values). The core practical payoff is maintainability: once logic lives in one place, it can be called repeatedly and updated once when requirements change.

A first function can be created with `def` and a name, followed by parentheses for parameters. If the function body is intentionally empty, `pass` prevents syntax errors while leaving room to fill in later. Execution depends on calling the function: writing the function name alone refers to the function object (showing a memory location), while adding parentheses actually runs it. When a function doesn’t return anything, Python yields `None`, which shows up when the call is printed.

Adding code inside the function turns it into a tool that performs work. A simple example prints a greeting from inside the function. That leads directly to the “don’t repeat yourself” principle (DRY): instead of copying the same print statement across many lines, the program can call the same function multiple times. If a boss later changes punctuation from `!` to `.`, updating the function once updates every call site—whether there are four lines or hundreds spread across files.

The next step is returning data rather than just printing it. Using `return` makes the function call evaluate to the returned value, so the result can be assigned, printed, or fed into other operations. A helpful mental model treats a function like a black box: focus on inputs and the output it returns, not the internal mechanics. This matters because returned values behave like normal data types. For instance, if a function returns a string, string methods such as `.upper()` can be chained onto the function call result.

Parameters customize behavior. Introducing a required parameter like `greeting` forces callers to supply an argument; omitting it triggers a “missing required positional argument” error. Parameters can also have defaults, such as `name='...'`, allowing calls to succeed even when that argument isn’t provided. Defaulted parameters make functions more flexible while keeping call sites concise.

Python also enforces ordering rules: required positional arguments must come before keyword arguments. For more advanced flexibility, `*args` and `**kwargs` accept an arbitrary number of positional and keyword arguments. Inside such a function, `args` arrives as a tuple of positional values, while `kwargs` arrives as a dictionary of keyword values. The same syntax can be used in reverse when calling a function: `*` unpacks a list into positional arguments, and `**` unpacks a dictionary into keyword arguments.

To tie everything together, the tutorial walks through two small functions modeled after Python’s standard library style: `isLeap` determines whether a year is a leap year using divisibility rules, and `daysInMonth` returns the number of days in a given month, including the February leap-year exception. By running these functions with specific inputs (e.g., 2017 vs. 2020, February month=2), the logic demonstrates how arguments drive return values and how multiple functions can cooperate to produce correct results.

Cornell Notes

Python functions package instructions into reusable blocks defined with `def`. Calling a function runs it; omitting parentheses prints the function object instead. If a function doesn’t use `return`, the call evaluates to `None`; using `return` makes the function call equal to the returned value, enabling chaining like `hello().upper()` when the return value is a string. Parameters can be required or have defaults, and missing required arguments raise errors. For variable inputs, `*args` collects positional arguments into a tuple and `**kwargs` collects keyword arguments into a dictionary, and `*`/`**` can also unpack lists/dicts when calling functions.

What’s the practical difference between referencing a function and executing it in Python?

Referencing happens when the function name appears without parentheses; printing that shows a function object and its memory location. Execution happens when the function name is followed by `()`, which runs the function body. If the function doesn’t return a value, the call evaluates to `None`, so printing the call shows `None`.

Why does returning values matter more than printing inside a function?

Printing inside a function performs output immediately but doesn’t produce a value for later use. Returning a value makes the function call itself equal to that value, so the result can be assigned, printed, or passed into other operations. In the tutorial, a function returning a string can be treated like a string and chained with methods such as `.upper()`.

How do required parameters and default parameters change function calls?

A parameter without a default is required; calling the function without it triggers an error like “missing one required positional argument greeting.” A parameter with a default (e.g., `name='...'`) allows the function to run even when the caller omits that argument, using the default instead. Passing a value overrides the default.

What do `*args` and `**kwargs` do, and what types do they become inside the function?

`*args` accepts an arbitrary number of positional arguments and stores them as a tuple named `args` (by convention). `**kwargs` accepts an arbitrary number of keyword arguments and stores them as a dictionary named `kwargs` (by convention). The function can then iterate or inspect these collections.

How does argument unpacking work when calling a function with `*` and `**`?

When calling, `*` unpacks a sequence (like a list) into positional arguments, and `**` unpacks a mapping (like a dictionary) into keyword arguments. The tutorial demonstrates this by passing a list of courses and a dictionary of student info into `student info`, using `*courses` and `**info` so the function receives the same values as if they were provided individually.

How do the leap-year and days-in-month examples demonstrate inputs driving outputs?

`isLeap(year)` returns `True` or `False` based on divisibility rules (divisible by 4, not by 100 unless also divisible by 400). `daysInMonth(year, month)` checks that `month` is between 1 and 12, returns 29 for February when `isLeap(year)` is true, and otherwise returns the appropriate day count from a `month days` list. Running with 2017 vs. 2020 shows the leap-year branch changing February’s result.

Review Questions

  1. When does a Python function call evaluate to `None`, and how can you change that behavior?
  2. How do default parameter values affect whether a function call raises an error?
  3. Explain the difference between `*args` and `**kwargs`, including what data types they become inside the function.

Key Points

  1. 1

    Define functions with `def` and use parentheses to execute them; parentheses are what trigger the function’s code.

  2. 2

    Use `pass` to create an empty function body without causing errors.

  3. 3

    Avoid repeating logic across the codebase by calling the same function multiple times (DRY).

  4. 4

    Use `return` to make function calls evaluate to useful values rather than relying on printing.

  5. 5

    Required parameters must be provided; default parameters allow calls to omit those arguments.

  6. 6

    Follow Python’s argument ordering rules: required positional arguments come before keyword arguments.

  7. 7

    Use `*args` and `**kwargs` to accept variable numbers of positional and keyword arguments, and use `*`/`**` to unpack lists and dictionaries when calling.

Highlights

Calling a function requires parentheses; without them, Python treats the name as a function object rather than running it.
A function that doesn’t `return` anything produces `None`, while `return` makes the call equal to the returned value.
Returning a string enables chaining string methods directly on the function call result (e.g., `.upper()`).
`*args` becomes a tuple and `**kwargs` becomes a dictionary, making it easy to handle unknown numbers of inputs.
`isLeap` and `daysInMonth` show how multiple functions can work together: leap-year logic feeds directly into February’s day count.

Topics

  • Python Functions
  • Return Values
  • Parameters Defaults
  • Variable Arguments
  • Leap Year Logic

Mentioned

  • DRY