2.1 Why do we need Functions?
Imagine you are writing a report-card program. You need to calculate the percentage for Asha, Rahul, Riya and 47 other students. Without functions, you would have to type the same formula total/5 fifty times — and if the formula ever changes, you’d have to edit fifty places. With a function called percentage(), you write the formula once and call it fifty times.
- Re-use — write the logic once, call it many times.
- Readability — a call like
area(l, b)reads like plain English. - Easy maintenance — fix or improve the code in one place only.
- Decomposition — break a big problem into small, independent pieces.
2.2 Types of Functions in Python
Every function you call in Python belongs to one of three families:
| Type | Where it comes from | Who wrote it | Example |
|---|---|---|---|
| Built-in | Part of Python itself — always available | Python authors | print(), len(), input() |
| Module | Defined inside a module you import | Library authors | math.sqrt(), random.randint() |
| User-defined | Defined by you using def | You, the programmer | def percentage(total): … |
2.2.1 Built-in Functions
Python comes with about seventy ready-made functions. You don’t have to import anything — they are always ready.
2.2.2 Module Functions
Functions that live inside modules (organised libraries of related code). You must import the module first.
2.2.3 User-defined Functions (UDF)
Whenever the problem needs logic that Python doesn’t already provide, you write your own function. These are the focus of the rest of this chapter.
2.3 Your First User-defined Function
2.3.1 Syntax of a function definition
def— the keyword that starts a definition.- function name — follows the same rules as any identifier.
- parameters in parentheses — zero or more, separated by commas.
- colon at the end of the header, followed by an indented body.
- return (optional) — sends a value back to the caller.
2.3.2 A tiny working example
2.3.3 Defining vs. Calling — an important distinction
def) only creates the function. Nothing runs yet — Python just remembers the recipe. The body runs only when the function is called by name, with () after it.
2.3.4 Docstring — documenting your function
A triple-quoted string placed as the very first line of the body is called a docstring. It becomes the function’s help text.
2.4 Arguments and Parameters
2.4.1 Parameter vs. Argument — what’s the difference?
| Parameter | Argument | |
|---|---|---|
| Where it appears | Inside the def () line | Inside the call () |
| What it is | A variable name — a placeholder | A real value being supplied |
| Also called | Formal parameter | Actual parameter |
2.4.2 Positional Arguments
When you call the function, Python matches arguments to parameters by position — the first argument fills the first parameter, the second fills the second, and so on.
2.4.3 Keyword Arguments
To avoid ordering mistakes, you can write parameter=value in the call. Order no longer matters.
2.4.4 Default Arguments
Sometimes most calls use the same value for a parameter. You can give it a default — callers may then omit it.
SyntaxError:
2.4.5 Mixing positional, keyword & default — the golden rule
In one call you can combine all three, but the order inside the call must be:
- Positional arguments first
- Keyword arguments after that
2.5 The return Statement
So far our functions only printed things. A more powerful pattern is a function that sends back a value — so the caller can store it in a variable, pass it to another function, or use it in an expression.
2.5.1 A function that returns one value
return, the function stops immediately — any code below return is never reached.
2.5.2 A function that returns multiple values
Write the values separated by commas after return; Python packs them into a tuple. The caller unpacks with multiple variables on the left of =.
2.5.3 A function that returns nothing — None
If a function has no return (or writes just return with no value), it returns the special value None.
2.5.4 return vs print — the classic confusion
print(x)— shows the value on screen, but the function still returnsNone.return x— sends the value back to the caller; the caller can do anything with it (store, print, use in an expression).
2.6 Flow of Execution
Python executes the file top-to-bottom. When it meets a def, it remembers the function but does NOT run the body yet. The body runs only when the function is called. After the call finishes, control returns to the line that called it.
2.7 Scope of a Variable
2.7.1 Local Scope
A variable created inside a function body exists only while that function is running. Trying to access it outside raises NameError.
2.7.2 Global Scope
Variables defined at the top level of the file are global. Any function can read them.
2.7.3 The LEGB rule — name lookup order
When Python sees a name inside a function, it searches four scopes in this order:
- Local — the current function
- Enclosing — surrounding function (nested functions)
- Global — top level of the module
- Built-in — names like
print,len,range
The first match wins.
2.7.4 The global keyword
A function can read a global variable but cannot reassign it unless you declare global.
Why the error? Because the moment Python sees count = ... inside the function, it marks count as a local variable for this function — but then count + 1 tries to read that local value before it was set.
Two ways to fix it:
global. Functions that modify global state are harder to test and debug.
2.8 Passing Mutable vs Immutable Arguments
int, float, str, tuple, bool), the function can’t change the original. If it is mutable (list, dict, set), the function can change the original.
2.8.1 Immutable argument — original is safe
2.8.2 Mutable argument — original is changed!
add_item(nums.copy()) or add_item(nums[:]).
2.9 CBSE-style Worked Programs
2.9.1 Function to check whether a number is even or odd
2.9.2 Function with default arguments — simple interest
2.9.3 Function returning multiple values — min and max of a list
2.9.4 Factorial using a function
2.9.5 Count vowels in a string — using a function
2.9.6 Function to reverse a string
2.9.7 Using global — a web-visitor counter
2.9.8 Decomposition — a mini report-card
A bigger problem, solved by calling three small functions one after another.
2.10 Common Mistakes to Avoid
| # | Mistake | Fix |
|---|---|---|
| 1 | Forgetting (): while calling | greet(), not just greet (that’s only the function object) |
| 2 | Using print where you needed return | Ask: “does the caller need the value?”. If yes → return |
| 3 | Reassigning a global without global | Declare global var, or return a new value |
| 4 | Mutable default like def f(a=[]) | Use a=None and create the list inside the body |
| 5 | Non-default parameter after a default | Re-order: defaults must come last |
| 6 | Using a local variable outside its function | Return it and store in a variable in the caller |
Quick-revision summary
- Three kinds of functions: built-in (
len,print…), module (math.sqrt…), user-defined (written by you withdef). - Function header:
def name(params):— followed by an indented body and an optionalreturn. - Parameter is the placeholder in
def; argument is the real value in the call. - Argument kinds: positional, keyword, default. In a call, positional come first, then keyword; defaults must be the last parameters.
returnsends a value back and stops the function. Multiple values are returned as a tuple.- A function without
returnreturnsNone. - Scope — names are searched in LEGB order. To reassign a global from inside, use
global. - Immutable arguments are safe; mutable arguments can be modified by the function.