Python Functions – Comprehensive Class Notes
Introduction to Functions
Why Use Functions?
- Large programs are difficult to manage, so we divide them into smaller units called functions
- Functions are groups of statements under a name that can be called from other parts of the program
- Example: School Management Software with separate functions for:
- Student registration
- Fee collection
- Library book issuing
- TC generation
- Result declaration
Modularization
- A set of functions stored in a file is called a module
- This approach is called modularization, making programs easier to:
- Understand
- Test
- Maintain
- Commonly used modules are called libraries
Types of Functions
- Built-in functions (predefined in Python)
- User-defined functions (created by programmers)
Advantages of Functions
- Easier Program Handling: Work with small parts at a time
- Reduced Lines of Code (LoC):
- Write common code once and call it from anywhere
- Avoids repetition
- Easy Updating:
- Changes needed in only one place
- Without functions, you’d need to update every occurrence
User-Defined Functions
Definition
A function is a set of statements that performs a specific task and can be reused (also called sub-routine, methods, procedure, or subprogram).
Syntax
def function_name([parameters]): """docstring""" # optional documentation statement(s) return [expression] # optional
Key Points
def
keyword marks the start of the function header- Function names must be unique and follow Python identifier rules
- Parameters are optional (within parentheses)
- Colon (
:
) ends the function header - Contains one or more statements
- Optional
return
statement to send back a value - Must be called/invoked to execute
Types of User-Defined Functions
- No arguments and no return value (void functions)
- With arguments but no return value
- With arguments and return value
- No argument but return value
1. No Arguments and No Return
def welcome(): print("Padharo Mhare Desh...") print("Ram Ram Sa...") welcome() # Function call
2. With Parameters but No Return
def table(num): for i in range(1,11): print(num,"x",i,"=",num*i) n = int(input("Enter Any number: ")) table(n)
3. With Parameters and Return
def cube(num): return num*num*num n = int(input("Enter Any Number: ")) print("Cube is:", cube(n))
4. No Argument but Return Value
def get_pi(): return 3.14159 print("PI value:", get_pi())
Parameters vs Arguments
- Parameters (Formal Arguments): Variables in function definition
- Arguments (Actual Arguments): Values passed to function during call
Example
import math def area(r): # 'r' is parameter return math.pi * r * r radius = int(input("Enter Radius: ")) print("Area:", area(radius)) # 'radius' is argument
Types of Arguments
- Positional arguments: Passed in correct positional orderpythonCopyDownloaddef divide(a, b): print(a/b) divide(20, 10) # 2.0 divide(10, 20) # 0.5
- Default arguments: Parameters with default valuespythonCopyDownloaddef drawline(symb=”$”, times=20): print(symb * times) drawline() # Uses defaults drawline(“@”) # Custom symbol drawline(“#”,40) # Custom both
- Keyword (Named) arguments: Pass arguments by parameter namepythonCopyDownloaddrawline(times=10, symb=’*’) # Order doesn’t matter
- Variable-length arguments: Accept arbitrary number of argumentspythonCopyDownloaddef average(*args): return sum(args)/len(args)
Rules for Combining Arguments
- Positional arguments must come before keyword arguments
- Can’t specify a value for an argument more than once
- All required arguments must be provided
Returning Multiple Values
Python allows returning multiple values (as a tuple):
def add10(x, y, z): return x+10, y+10, z+10 # Option 1: Store as tuple result = add10(10, 20, 30) # (20, 30, 40) # Option 2: Unpack into variables a, b, c = add10(1, 2, 3) # a=11, b=12, c=13
Scope of Variables
Global Scope
- Variables defined outside all functions
- Accessible throughout the program
- Lifetime: Entire program execution
Local Scope
- Variables defined inside a function
- Accessible only within that function
- Lifetime: Function execution duration
- Includes function parameters
Example
value = 600 # Global def check(): value = 100 # Local print(value) # 100 print(value) # 600 check() # 100 print(value) # 600 (global unchanged)
global
Keyword
To modify global variables inside a function:
count = 0 def increment(): global count count += 1
LEGB Rule (Name Resolution Order)
- Local
- Enclosing
- Global
- Built-in
Mutability and Functions
Immutable Objects (numbers, strings, tuples)
- Changes create new objects
- Changes inside function don’t affect original
def modify(num): num += 10 # Creates new object print("Inside:", num, id(num)) value = 100 print("Before:", value, id(value)) modify(value) # Inside: 110 (different id) print("After:", value, id(value)) # Original unchanged
Mutable Objects (lists, dictionaries)
- Changes affect original object
- Modifications inside function are reflected outside
def update_list(lst): lst[0] = 99 # Modifies original numbers = [1, 2, 3] update_list(numbers) print(numbers) # [99, 2, 3]
Passing Different Data Types to Functions
Strings (Immutable)
def count_vowels(s): vowels = "aeiouAEIOU" return sum(1 for char in s if char in vowels) print(count_vowels("Hello")) # 2
Lists (Mutable)
def double_odds_halve_evens(lst): for i in range(len(lst)): if lst[i] % 2 == 0: lst[i] //= 2 else: lst[i] *= 2 numbers = [11, 20, 30, 40] double_odds_halve_evens(numbers) print(numbers) # [22, 10, 15, 20]
Tuples (Immutable)
def count_even_odd(t): even = sum(1 for num in t if num%2 == 0) return even, len(t)-even nums = (10, 21, 30, 43) print(count_even_odd(nums)) # (2, 2)
Dictionaries (Mutable)
def update_value(d, key, value): d[key] = value student = {'name': 'Amit', 'age': 20} update_value(student, 'age', 21) print(student) # {'name': 'Amit', 'age': 21}
The main()
Function
- Not mandatory in Python but good practice
- Helps organize code
- Uses
__name__
variable to check if module is run directly
def main(): print("This is the main function") if __name__ == "__main__": main()
Recursion
Definition
A function that calls itself to solve smaller instances of a problem.
Requirements
- Base Case: Condition to stop recursion
- Recursive Case: Calls itself with modified parameters
Example: Factorial
def factorial(n): if n == 1: # Base case return 1 else: # Recursive case return n * factorial(n-1)
Example: Fibonacci
def fibonacci(n):
if n <= 1:
return n
else:
return fibonacci(n-1) + fibonacci(n-2)
Characteristics
- Uses stack memory for each call
- Can be less efficient than iteration
- Essential for problems like tree/graph traversals