NANDHOO.

Functions


Functions are named, reusable blocks of code that perform a specific task. They are one of the most important tools in programming because they let you write code once and use it many times.


Why This Chapter Matters


Well-written functions make programs easier to read, test, and change. Almost every Python program you will write depends on functions.


  • they reduce code repetition (DRY: Don't Repeat Yourself)
  • they give code clear names and structure
  • they let you test pieces of code in isolation
  • they make programs easier to change and maintain

Defining a Function


Use the def keyword, followed by the function name, parameters in parentheses, and a colon.


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

message = greet("Asha") print(message) # Hello, Asha!


Parameters and Arguments


  • Parameters are the variable names in the function definition
  • Arguments are the actual values passed when calling the function

def add(a, b):     # a and b are parameters
    return a + b

result = add(3, 7) # 3 and 7 are arguments print(result) # 10


The return Statement


return sends a value back to the caller and ends the function immediately.


def square(n):
    return n * n

print(square(5)) # 25


Without return, a function returns None:


def say_hello():
    print("Hello!")

result = say_hello() print(result) # None


A function can return multiple values as a tuple:


def min_max(numbers):
    return min(numbers), max(numbers)

low, high = min_max([3, 1, 9, 4]) print(low, high) # 1 9


Default Parameters


Provide a default value so the argument becomes optional:


def power(base, exponent=2):
    return base ** exponent

print(power(3)) # 9 (exponent defaults to 2) print(power(3, 3)) # 27


Keyword Arguments


Call a function by naming the parameters explicitly. Order does not matter.


def describe(name, age, city):
    return f"{name}, age {age}, from {city}"

print(describe(age=16, city="Mumbai", name="Leo"))


Positional-Only and Keyword-Only Arguments


def greet(name, /, *, greeting="Hello"):
    # name is positional-only (before /)
    # greeting is keyword-only (after *)
    return f"{greeting}, {name}!"

print(greet("Asha")) # Hello, Asha! print(greet("Asha", greeting="Hi")) # Hi, Asha!


*args — Variable Positional Arguments


Accept any number of positional arguments as a tuple:


def add_all(*numbers):
    return sum(numbers)

print(add_all(1, 2, 3)) # 6 print(add_all(10, 20, 30, 40)) # 100


**kwargs — Variable Keyword Arguments


Accept any number of keyword arguments as a dictionary:


def profile(**info):
    for key, value in info.items():
        print(f"{key}: {value}")

profile(name="Mina", age=15, hobby="coding")


Combining All Argument Types


The order is: positional, *args, keyword-only, **kwargs:


def example(a, b, *args, keyword=True, **kwargs):
    print(a, b, args, keyword, kwargs)

Scope: Local vs Global Variables


A variable created inside a function is local to that function:


def my_function():
    local_var = "I only exist here"
    print(local_var)

my_function()

print(local_var) # NameError — not accessible here


A variable defined outside functions is global:


app_name = "NANDHOO"

def show_name(): print(app_name) # can read a global variable


show_name()


Use global to modify a global variable from inside a function (use sparingly):


counter = 0

def increment(): global counter counter += 1


increment() print(counter) # 1


Lambda Functions (Anonymous Functions)


A lambda is a small, single-expression function without a name.


square = lambda x: x ** 2
print(square(5))   # 25

Often used with built-in functions:

numbers = [3, 1, 4, 1, 5, 9] numbers.sort(key=lambda x: -x) # sort descending print(numbers) # [9, 5, 4, 3, 1, 1]


Docstrings


Document what a function does using a docstring — the first string in the body:


def calculate_area(radius):
    """
    Calculate the area of a circle.

Args:
    radius (float): The radius of the circle.

Returns:
    float: The area of the circle.
"""
import math
return math.pi * radius ** 2

Access it with help(calculate_area) or calculate_area.__doc__.


Higher-Order Functions


Functions can accept other functions as arguments or return them.


map() — Transform Each Item


numbers = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, numbers))
print(doubled)   # [2, 4, 6, 8, 10]

filter() — Keep Items That Match


numbers = [1, 2, 3, 4, 5, 6]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)   # [2, 4, 6]

Returning a Function


def make_multiplier(factor):
    def multiply(x):
        return x * factor
    return multiply

triple = make_multiplier(3) print(triple(10)) # 30


Recursion


A function that calls itself is recursive. It must have a base case to stop.


def factorial(n):
    if n == 0:
        return 1
    return n * factorial(n - 1)

print(factorial(5)) # 120


Common Mistakes


  • forgetting return (function returns None silently)
  • using mutable default arguments like def func(items=[]) — use None instead
  • modifying a global variable without global keyword (causes UnboundLocalError)
  • very long functions with too many responsibilities (prefer small, focused functions)

Mini Exercises


  1. Write a function is_even(n) that returns True if n is even.
  2. Write a function celsius_to_fahrenheit(c) with the formula (c * 9/5) + 32.
  3. Write a function using *args that returns the average of all arguments.
  4. Write a function that takes another function as an argument and calls it.
  5. Write a recursive function to compute the nth Fibonacci number.

Review Questions


  1. What is the difference between a parameter and an argument?
  2. What does a function return when it has no return statement?
  3. What is the difference between *args and **kwargs?
  4. When would you use a lambda function instead of a regular function?
  5. What is a docstring and why should you write one?

Reference Checklist


  • I can define functions with def and call them
  • I understand positional, keyword, default, *args, and **kwargs
  • I understand local vs global scope
  • I can write and use lambda functions
  • I can write recursive functions with a base case
  • I can write proper docstrings