Functions in Python
# Functions in Python
Welcome to Chapter 13! Functions are the building blocks of organized, reusable code. Instead of repeating the same code, you write it once as a function and call it whenever needed.
---
1. Learning Objectives
- Define and call functions.
- Use parameters, arguments, and return values.
- Understand variable scope (local vs global).
- Use default, *args, and **kwargs parameters.
- Write recursive functions.
---
2. Defining and Calling Functions
```python id="py13_ex1" # Defining a function def greet(name): """Greet a user by name.""" print(f"Hello, {name}! Welcome! 👋")
# Calling the function greet("Alice") # Hello, Alice! Welcome! 👋 greet("Bob") # Hello, Bob! Welcome! 👋
python id="py13ex2" def add(a, b): """Return the sum of two numbers.""" return a + b
result = add(10, 20) print(f"Sum: {result}") # Sum: 30
# Multiple return values def getstats(numbers): return min(numbers), max(numbers), sum(numbers) / len(numbers)
low, high, avg = get_stats([10, 20, 30, 40, 50]) print(f"Min: {low}, Max: {high}, Avg: {avg}")
python id="py13_ex3" def power(base, exponent=2): return base ** exponent
print(power(5)) # 25 (default exponent=2) print(power(5, 3)) # 125 print(power(2, 10)) # 1024
python id="py13ex4" def createprofile(name, age, city="Unknown"): print(f"Name: {name}, Age: {age}, City: {city}")
createprofile("Alice", 25, "NYC") createprofile(age=30, name="Bob") # Keyword args (any order)
python id="py13ex5" # *args — accept any number of positional arguments def total(*args): print(f"Args: {args}") # Tuple return sum(args)
print(total(1, 2, 3)) # 6 print(total(10, 20, 30, 40)) # 100
# kwargs — accept any number of keyword arguments def printinfo(kwargs): for key, value in kwargs.items(): print(f" {key}: {value}")
print_info(name="Alice", age=25, city="NYC")
# Combined def func(a, b, *args, **kwargs): print(f"a={a}, b={b}, args={args}, kwargs={kwargs}")
func(1, 2, 3, 4, x=5, y=6)
python id="py13_ex6" x = "global" # Global variable
def func(): x = "local" # Local variable print(f"Inside: {x}") # local
func() print(f"Outside: {x}") # global
# Using global keyword counter = 0
def increment(): global counter counter += 1
increment() increment() print(counter) # 2
Scope Diagram: ┌─────────────────────────┐ │ Global Scope │ │ x = "global" │ │ ┌───────────────────┐ │ │ │ Local Scope │ │ │ │ x = "local" │ │ │ │ (shadows global) │ │ │ └───────────────────┘ │ └─────────────────────────┘
python id="py13_ex7" # Factorial using recursion def factorial(n): if n <= 1: # Base case return 1 return n * factorial(n - 1) # Recursive case
print(factorial(5)) # 120 = 5*4*3*2*1
# Fibonacci def fib(n): if n <= 1: return n return fib(n-1) + fib(n-2)
for i in range(10): print(fib(i), end=" ") # 0 1 1 2 3 5 8 13 21 34
Factorial(4) Call Stack: factorial(4) → 4 * factorial(3) → 3 * factorial(2) → 2 * factorial(1) → 1 (base case) → 2 * 1 = 2 → 3 * 2 = 6 → 4 * 6 = 24
python id="py13ex8" def greet(name: str) -> str: return f"Hello, {name}!"
def add(a: int, b: int) -> int: return a + b
def getinfo(name: str, age: int = 0) -> dict: return {"name": name, "age": age}
python id="py13ex9" def validatepassword(password: str) -> tuple: errors = [] if len(password) < 8: errors.append("Must be 8+ characters") if not any(c.isupper() for c in password): errors.append("Need uppercase letter") if not any(c.isdigit() for c in password): errors.append("Need a digit") isvalid = len(errors) == 0 return isvalid, errors
valid, errs = validatepassword("hello") print(f"Valid: {valid}, Errors: {errs}")
valid, errs = validatepassword("Hello123!")
print(f"Valid: {valid}, Errors: {errs}")
``
---
9. Common Mistakes
-
1.
Mutable default arguments: def f(lst=[])
— useNoneinstead.
-
2.
Forgetting return: Functions return None
by default.
-
3.
Modifying global variables without global
:Creates local variable instead.
- 4. Infinite recursion: Always need a base case.
---
10. MCQs with Answers
Q1: Functions without return statement return: A) 0 B) "" C) None D) Error Answer: C
Q2: *args collects arguments into a:
A) List B) Tuple C) Dict D) Set
Answer: B
Q3: kwargs collects arguments into a:
A) List B) Tuple C) Dict D) Set
Answer: C
Q4: Default parameters must be: A) First B) Last C) Anywhere D) In middle Answer: B — After non-default parameters.
Q5: Local variable scope is: A) Everywhere B) Inside function only C) Outside function D) Global Answer: B
Q6: What is recursion? A) Looping B) Function calling itself C) Importing D) Error handling Answer: B
Q7: Type hints are: A) Enforced B) Optional documentation C) Required in 3.10+ D) Only for classes Answer: B — They're hints, not enforced at runtime.
Q8: def f(a, b=5, c) is:
A) Valid B) SyntaxError
Answer: B — Default params must come after non-default.
Q9: What does global keyword do?
A) Creates variable B) Accesses global scope variable C) Deletes variable D) Imports module
Answer: B
Q10: factorial(0) should return:
A) 0 B) 1 C) Error D) None
Answer: B — 0! = 1 by mathematical definition.
---
11. Interview Questions
- 1. Difference between function and method? Functions are standalone; methods are functions bound to objects.
- 2. What is a closure? A function that captures variables from its enclosing scope.
- 3. Why are mutable default args dangerous? The default object is shared across calls, leading to unexpected behavior.
- 4. What is the call stack? A stack tracking function calls; each call adds a frame, each return removes one.
-
5.
pass
vsreturn None?passis a no-op placeholder;return Noneexplicitly exits and returns None.
---
12. Summary
-
Functions are defined with def
, called by name with arguments.
-
Use return
to send values back; functions returnNoneby default.
-
*args
captures positional args as tuple;kwargscaptures keyword args as dict.
- Variables have local scope inside functions, global outside.
- Recursion solves problems by having functions call themselves with a base case.
---
13. Next Chapter Recommendation
In Chapter 14: Lambda Functions and Higher-Order Functions, you'll learn anonymous functions, map(), filter(), and reduce()`! 🚀