## 1. Definitions
- **Function**: A named block of code that performs a specific task and can be reused multiple times in a program.
- **Parameter**: A variable listed in the function definition that receives values when the function is called.
- **Argument**: The actual value passed to a function when it is called.
- **Function Call**: The process of executing a function by using its name followed by parentheses.
- **Return Value**: The value that a function sends back to the calling code using the `return` statement.
- **Scope**: The region of a program where a variable is accessible.
- **Local Variable**: A variable declared inside a function, accessible only within that function.
- **Global Variable**: A variable declared outside all functions, accessible throughout the program.
- **Mutable Object**: An object whose content can be changed after creation (e.g., list, dictionary).
- **Immutable Object**: An object whose content cannot be changed after creation (e.g., int, float, string, tuple).
---
## 2. Explanation of Concepts
### 3.1 Introduction
Functions are fundamental building blocks in Python programming that help in:
- Breaking down complex problems into smaller, manageable parts
- Avoiding code repetition (DRY principle - Don't Repeat Yourself)
- Making code more readable and maintainable
- Enabling code reusability across different parts of a program
### 3.2 Understanding Functions
#### 3.2.1 Calling/Invoking/Using a Function
A function is called by writing its name followed by parentheses. If the function requires arguments, they are placed inside the parentheses.
**Syntax:**
```
function_name(arguments)
```
#### 3.2.2 Python Function Types
Python has two main types of functions:
1. **Built-in Functions**: Pre-defined functions provided by Python
- Examples: `print()`, `input()`, `len()`, `type()`, `int()`, `float()`, `str()`
2. **User-defined Functions**: Functions created by programmers to perform specific tasks
- Defined using the `def` keyword
### 3.3 Defining Functions in Python
Functions are defined using the `def` keyword followed by function name, parameters, and a colon.
**Basic Syntax:**
```
def function_name(parameters):
"""Docstring (optional)"""
# Function body
statement(s)
return value # optional
```
#### 3.3.1 Structure of a Python Program
A typical Python program with functions follows this structure:
1. Import statements
2. Global variable declarations
3. Function definitions
4. Main program code (function calls)
### 3.4 Flow of Execution in a Function Call
When a function is called:
1. Program control jumps to the function definition
2. Parameters receive the values of arguments
3. Function body executes line by line
4. If `return` statement is encountered, the value is sent back
5. Control returns to the point where function was called
6. Program continues from the next statement
#### 3.4.1 Arguments and Parameters
- **Parameters** are variables in the function definition
- **Arguments** are actual values passed during function call
- The number and order of arguments must match the parameters (unless default or keyword arguments are used)
### 3.5 Passing Parameters
#### 3.5.1 Positional/Required Arguments
Arguments are passed in the same order as parameters are defined. Position matters.
**Example:**
```
def greet(name, age):
print(f"Hello {name}, you are {age} years old")
greet("Rahul", 17) # name="Rahul", age=17
```
#### 3.5.2 Default Arguments
Parameters can have default values. If no argument is passed, the default value is used.
**Example:**
```
def greet(name, age=16):
print(f"Hello {name}, you are {age} years old")
greet("Priya") # Uses default age=16
greet("Amit", 18) # Overrides default with 18
```
**Important Rule**: Default parameters must come after non-default parameters.
#### 3.5.3 Keyword (Named) Arguments
Arguments are passed using parameter names. Order doesn't matter.
**Example:**
```
def calculate(length, breadth, height):
return length *breadth* height
volume = calculate(height=10, length=5, breadth=3) # Order changed
```
#### 3.5.4 Using Multiple Argument Types Together
You can combine positional, default, and keyword arguments in a single function call.
**Rules:**
1. Positional arguments must come first
2. Keyword arguments must come after positional arguments
3. Default parameters must be defined after required parameters
**Example:**
```
def student_info(name, class_no, section='A', percentage=75):
print(f"{name} from Class {class_no}-{section} scored {percentage}%")
# Valid calls:
student_info("Neha", 12) # Uses defaults
student_info("Rohan", 12, 'B') # Overrides section
student_info("Priya", 12, percentage=85) # Keyword argument
student_info("Amit", 12, section='C', percentage=90) # Multiple keyword args
```
### 3.6 Returning Values From Functions
Functions can return values using the `return` statement. If no `return` is specified, the function returns `None`.
**Example:**
```
def add(a, b):
return a + b
result = add(5, 3) # result = 8
```
#### 3.6.1 Returning Multiple Values
Python functions can return multiple values as a tuple.
**Example:**
```
def calculate(a, b):
sum_val = a + b
diff = a - b
product = a * b
return sum_val, diff, product
s, d, p = calculate(10, 5) # s=15, d=5, p=50
```
### 3.7 Composition
Composition means using the output of one function as the input to another function.
**Example:**
```
def square(x):
return x * x
def double(x):
return 2 * x
# Composition: double(square(3))
result = double(square(3)) # square(3)=9, double(9)=18
```
### 3.8 Scope of Variables
**Scope** determines where a variable can be accessed in a program.
**Types of Scope:**
1. **Local Scope**: Variables declared inside a function
- Accessible only within that function
- Created when function is called, destroyed when function ends
2. **Global Scope**: Variables declared outside all functions
- Accessible throughout the program
- Exist for the entire program duration
**Example:**
```
x = 10 # Global variable
def my_function():
y = 5 # Local variable
print(x) # Can access global x
print(y) # Can access local y
my_function()
# print(y) # Error! y is not accessible outside function
```
#### 3.8.1 Name Resolution (Resolving Scope of a Name)
Python follows the **LEGB Rule** for name resolution:
- **L** - Local (inside function)
- **E** - Enclosing (in enclosing function, for nested functions)
- **G** - Global (module level)
- **B** - Built-in (Python's built-in names)
**Using `global` keyword:**
To modify a global variable inside a function, use the `global` keyword.
**Example:**
```
count = 0 # Global variable
def increment():
global count # Declare that we want to use global count
count = count + 1
increment()
print(count) # Output: 1
```
### 3.9 Mutable/Immutable Properties of Passed Data Objects
#### 3.9.1 Mutability/Immutability of Arguments/Parameters and Function Calls
**Immutable Objects**: int, float, string, tuple
- When passed to a function, changes inside the function don't affect the original object
- A new object is created if modified
**Mutable Objects**: list, dictionary, set
- When passed to a function, changes inside the function affect the original object
- The same object is modified, not a copy
**Example with Immutable (int):**
```
def modify_number(x):
x = x + 10
print("Inside function:", x)
num = 5
modify_number(num) # Inside function: 15
print("Outside:", num) # Outside: 5 (unchanged)
```
**Example with Mutable (list):**
```
def modify_list(lst):
lst.append(100)
print("Inside function:", lst)
my_list = [1, 2, 3]
modify_list(my_list) # Inside function: [1, 2, 3, 100]
print("Outside:", my_list) # Outside: [1, 2, 3, 100] (changed!)
```
---
## 3. Important Points
- A function must be **defined before** it is called in the program
- Function names follow the same rules as variable names (no spaces, no special characters except underscore)
- The `def` keyword is used to define a function
- Indentation is mandatory in Python functions
- A function can call itself (recursion) or other functions
- The `return` statement immediately exits the function
- A function can have multiple `return` statements but only one will execute
- Parameters with default values must come after parameters without defaults
- Once you use a keyword argument, all following arguments must also be keyword arguments
- Functions help in modular programming and code reusability
- Local variables are destroyed after function execution completes
- Use `global` keyword carefully as it can make debugging difficult
- Mutable objects passed to functions can be modified, affecting the original
- Immutable objects cannot be modified in-place; reassignment creates a new object
---
## 4. Syntax
### Function Definition
```
def function_name(parameter1, parameter2, ...):
"""Docstring explaining what function does"""
# Function body
statement(s)
return value # optional
```
### Function with Default Arguments
```
def function_name(param1, param2=default_value):
# Function body
return value
```
### Function with Multiple Return Values
```
def function_name(parameters):
# Function body
return value1, value2, value3
```
### Using global keyword
```
def function_name():
global variable_name
variable_name = new_value
```
---
## 5. Examples
### Example 1: Simple Function
```
def welcome():
print("Welcome to Python Programming!")
print("Let's learn functions")
welcome() # Function call
```
**Output:**
```
Welcome to Python Programming!
Let's learn functions
```
### Example 2: Function with Parameters
```
def calculate_percentage(marks, total):
percentage = (marks / total) * 100
return percentage
result = calculate_percentage(450, 500)
print(f"Percentage: {result}%")
```
**Output:**
```
Percentage: 90.0%
```
### Example 3: Function with Default Arguments
```
def book_ticket(name, destination, class_type="Economy"):
print(f"Ticket booked for {name}")
print(f"Destination: {destination}")
print(f"Class: {class_type}")
book_ticket("Rahul", "Mumbai")
book_ticket("Priya", "Delhi", "Business")
```
**Output:**
```
Ticket booked for Rahul
Destination: Mumbai
Class: Economy
Ticket booked for Priya
Destination: Delhi
Class: Business
```
### Example 4: Function with Keyword Arguments
```
def student_details(name, roll_no, marks):
print(f"Name: {name}")
print(f"Roll No: {roll_no}")
print(f"Marks: {marks}")
student_details(marks=95, name="Amit", roll_no=25)
```
**Output:**
```
Name: Amit
Roll No: 25
Marks: 95
```
### Example 5: Returning Multiple Values
```
def arithmetic_operations(a, b):
addition = a + b
subtraction = a - b
multiplication = a * b
division = a / b
return addition, subtraction, multiplication, division
add, sub, mul, div = arithmetic_operations(20, 4)
print(f"Addition: {add}")
print(f"Subtraction: {sub}")
print(f"Multiplication: {mul}")
print(f"Division: {div}")
```
**Output:**
```
Addition: 24
Subtraction: 16
Multiplication: 80
Division: 5.0
```
### Example 6: Scope of Variables
```
total_students = 50 # Global variable
def add_student():
global total_students
total_students = total_students + 1
print(f"Inside function: {total_students}")
print(f"Before function call: {total_students}")
add_student()
print(f"After function call: {total_students}")
```
**Output:**
```
Before function call: 50
Inside function: 51
After function call: 51
```
### Example 7: Mutable vs Immutable
```
# Immutable (String)
def change_name(name):
name = "New Name"
print(f"Inside function: {name}")
student_name = "Rahul"
change_name(student_name)
print(f"Outside function: {student_name}")
# Mutable (List)
def add_marks(marks_list):
marks_list.append(85)
print(f"Inside function: {marks_list}")
marks = [70, 80, 90]
add_marks(marks)
print(f"Outside function: {marks}")
```
**Output:**
```
Inside function: New Name
Outside function: Rahul
Inside function: [70, 80, 90, 85]
Outside function: [70, 80, 90, 85]
```
### Example 8: Composition
```
def celsius_to_kelvin(celsius):
return celsius + 273.15
def fahrenheit_to_celsius(fahrenheit):
return (fahrenheit - 32) * 5/9
# Composition: Convert Fahrenheit to Kelvin
temp_f = 98.6
temp_k = celsius_to_kelvin(fahrenheit_to_celsius(temp_f))
print(f"{temp_f}°F = {temp_k}K")
```
**Output:**
```
98.6°F = 310.15K
```
---
## 6. Tables / Diagrams
### Table 1: Types of Arguments
| Argument Type | Description | Example | Rules |
|--------------|-------------|---------|-------|
| **Positional** | Arguments passed in order | `func(10, 20)` | Must match parameter order |
| **Keyword** | Arguments passed by name | `func(a=10, b=20)` | Order doesn't matter |
| **Default** | Parameters with default values | `def func(a, b=10)` | Must be after required parameters |
| **Mixed** | Combination of above | `func(10, b=20)` | Positional first, then keyword |
### Table 2: Scope Comparison
| Feature | Local Variable | Global Variable |
|---------|---------------|-----------------|
| **Declaration** | Inside function | Outside all functions |
| **Accessibility** | Only within function | Throughout program |
| **Lifetime** | During function execution | Entire program runtime |
| **Modification** | Direct | Requires `global` keyword in function |
| **Example** | `def f(): x=5` | `x=5` (outside function) |
### Table 3: Mutable vs Immutable Objects
| Immutable Objects | Mutable Objects |
|------------------|-----------------|
| int | list |
| float | dictionary |
| string | set |
| tuple | bytearray |
| **Cannot be changed** | **Can be changed** |
| Changes create new object | Changes modify same object |
| Safe from unintended modification | Need careful handling in functions |
---
## 7. Common Errors / Misconceptions
### Error 1: Calling function before definition
```
# Wrong
greet() # Error: name 'greet' is not defined
def greet():
print("Hello")
```
**Correct:**
```
def greet():
print("Hello")
greet() # Function called after definition
```
### Error 2: Incorrect number of arguments
```
def add(a, b):
return a + b
result = add(5) # Error: missing 1 required positional argument: 'b'
```
### Error 3: Default parameter before required parameter
```
# Wrong
def student(age=17, name): # SyntaxError
print(name, age)
```
**Correct:**
```
def student(name, age=17): # Required before default
print(name, age)
```
### Error 4: Modifying global variable without `global` keyword
```
count = 0
def increment():
count = count + 1 # UnboundLocalError
increment()
```
**Correct:**
```
count = 0
def increment():
global count
count = count + 1
increment()
print(count) # Output: 1
```
### Error 5: Keyword argument before positional argument
```
def display(name, age, city):
print(name, age, city)
# Wrong
display(name="Rahul", 17, "Delhi") # SyntaxError
```
**Correct:**
```
display("Rahul", 17, city="Delhi") # Positional first, then keyword
```
### Misconception 1: Return statement is mandatory
- **Truth**: Functions without `return` automatically return `None`
- A function can perform actions without returning a value
### Misconception 2: All objects behave the same when passed to functions
- **Truth**: Immutable objects (int, string, tuple) cannot be modified in-place
- Mutable objects (list, dict, set) can be modified and changes reflect outside
### Misconception 3: Variables inside functions are accessible everywhere
- **Truth**: Local variables exist only during function execution
- They are destroyed once function completes
---
## 8. Exam-Oriented Short Notes
### Quick Revision Points
**Function Basics**
- Function = reusable block of code
- Syntax: `def function_name(parameters):`
- Must define before calling
- Use meaningful names
**Arguments and Parameters**
- **Parameter** = variable in definition
- **Argument** = actual value passed
- Types: Positional, Keyword, Default
**Order of Arguments**
1. Positional arguments (required)
2. Keyword arguments
3. Default parameters (in definition)
**Return Statement**
- Sends value back to caller
- Optional; `None` if not specified
- Can return multiple values as tuple
- Exits function immediately
**Scope Rules**
- **Local**: Declared inside function
- **Global**: Declared outside all functions
- Use `global` keyword to modify global variable inside function
- LEGB rule: Local → Enclosing → Global → Built-in
**Mutability**
- **Immutable**: int, float, string, tuple (safe from modification)
- **Mutable**: list, dict, set (can be modified in functions)
**Common Function Patterns**
- No parameters, no return: `def greet():`
- With parameters, no return: `def display(name):`
- No parameters, with return: `def get_value():`
- With parameters and return: `def add(a, b):`
**Important Rules**
- Default parameters must be after required ones
- Keyword arguments must be after positional ones
- Once a keyword argument is used, all following must be keyword
- Function names follow variable naming rules
- Indentation is mandatory
**Benefits of Functions**
- Code reusability
- Modularity
- Easy debugging
- Better organization
- Avoid repetition
---
## Sample Exam Questions & Answers
### Q1: What will be the output?
```
def modify(x, y):
x = x + 10
y.append(10)
a = 5
b = [1, 2, 3]
modify(a, b)
print(a, b)
```
**Answer:** `5 [1, 2, 3, 10]`
- `a` is immutable (int), so changes don't affect original
- `b` is mutable (list), so changes reflect outside
### Q2: Write a function to check if a number is prime.
```
def is_prime(n):
if n <= 1:
return False
for i in range(2, int(n0.5) + 1):
if n % i == 0:
return False
return True
print(is_prime(17)) # True
print(is_prime(10)) # False
```
### Q3: Find and correct the error:
```
def calculate(x, y=10, z):
return x + y + z
```
**Error:** Default parameter `y` before required parameter `z`
**Correct:**
```
def calculate(x, z, y=10):
return x + y + z
```
### Q4: What is the output?
```
x = 10
def func():
x = 20
print(x)
func()
print(x)
```
**Answer:**
```
20
10
```
- Inside function: local `x = 20`
- Outside: global `x = 10` (unchanged)
### Q5: Write a function that returns both quotient and remainder.
```
def divide(dividend, divisor):
quotient = dividend // divisor
remainder = dividend % divisor
return quotient, remainder
q, r = divide(17, 5)
print(f"Quotient: {q}, Remainder: {r}")
```
**Output:** `Quotient: 3, Remainder: 2`
- **Function**: A named block of code that performs a specific task and can be reused multiple times in a program.
- **Parameter**: A variable listed in the function definition that receives values when the function is called.
- **Argument**: The actual value passed to a function when it is called.
- **Function Call**: The process of executing a function by using its name followed by parentheses.
- **Return Value**: The value that a function sends back to the calling code using the `return` statement.
- **Scope**: The region of a program where a variable is accessible.
- **Local Variable**: A variable declared inside a function, accessible only within that function.
- **Global Variable**: A variable declared outside all functions, accessible throughout the program.
- **Mutable Object**: An object whose content can be changed after creation (e.g., list, dictionary).
- **Immutable Object**: An object whose content cannot be changed after creation (e.g., int, float, string, tuple).
---
## 2. Explanation of Concepts
### 3.1 Introduction
Functions are fundamental building blocks in Python programming that help in:
- Breaking down complex problems into smaller, manageable parts
- Avoiding code repetition (DRY principle - Don't Repeat Yourself)
- Making code more readable and maintainable
- Enabling code reusability across different parts of a program
### 3.2 Understanding Functions
#### 3.2.1 Calling/Invoking/Using a Function
A function is called by writing its name followed by parentheses. If the function requires arguments, they are placed inside the parentheses.
**Syntax:**
```
function_name(arguments)
```
#### 3.2.2 Python Function Types
Python has two main types of functions:
1. **Built-in Functions**: Pre-defined functions provided by Python
- Examples: `print()`, `input()`, `len()`, `type()`, `int()`, `float()`, `str()`
2. **User-defined Functions**: Functions created by programmers to perform specific tasks
- Defined using the `def` keyword
### 3.3 Defining Functions in Python
Functions are defined using the `def` keyword followed by function name, parameters, and a colon.
**Basic Syntax:**
```
def function_name(parameters):
"""Docstring (optional)"""
# Function body
statement(s)
return value # optional
```
#### 3.3.1 Structure of a Python Program
A typical Python program with functions follows this structure:
1. Import statements
2. Global variable declarations
3. Function definitions
4. Main program code (function calls)
### 3.4 Flow of Execution in a Function Call
When a function is called:
1. Program control jumps to the function definition
2. Parameters receive the values of arguments
3. Function body executes line by line
4. If `return` statement is encountered, the value is sent back
5. Control returns to the point where function was called
6. Program continues from the next statement
#### 3.4.1 Arguments and Parameters
- **Parameters** are variables in the function definition
- **Arguments** are actual values passed during function call
- The number and order of arguments must match the parameters (unless default or keyword arguments are used)
### 3.5 Passing Parameters
#### 3.5.1 Positional/Required Arguments
Arguments are passed in the same order as parameters are defined. Position matters.
**Example:**
```
def greet(name, age):
print(f"Hello {name}, you are {age} years old")
greet("Rahul", 17) # name="Rahul", age=17
```
#### 3.5.2 Default Arguments
Parameters can have default values. If no argument is passed, the default value is used.
**Example:**
```
def greet(name, age=16):
print(f"Hello {name}, you are {age} years old")
greet("Priya") # Uses default age=16
greet("Amit", 18) # Overrides default with 18
```
**Important Rule**: Default parameters must come after non-default parameters.
#### 3.5.3 Keyword (Named) Arguments
Arguments are passed using parameter names. Order doesn't matter.
**Example:**
```
def calculate(length, breadth, height):
return length *breadth* height
volume = calculate(height=10, length=5, breadth=3) # Order changed
```
#### 3.5.4 Using Multiple Argument Types Together
You can combine positional, default, and keyword arguments in a single function call.
**Rules:**
1. Positional arguments must come first
2. Keyword arguments must come after positional arguments
3. Default parameters must be defined after required parameters
**Example:**
```
def student_info(name, class_no, section='A', percentage=75):
print(f"{name} from Class {class_no}-{section} scored {percentage}%")
# Valid calls:
student_info("Neha", 12) # Uses defaults
student_info("Rohan", 12, 'B') # Overrides section
student_info("Priya", 12, percentage=85) # Keyword argument
student_info("Amit", 12, section='C', percentage=90) # Multiple keyword args
```
### 3.6 Returning Values From Functions
Functions can return values using the `return` statement. If no `return` is specified, the function returns `None`.
**Example:**
```
def add(a, b):
return a + b
result = add(5, 3) # result = 8
```
#### 3.6.1 Returning Multiple Values
Python functions can return multiple values as a tuple.
**Example:**
```
def calculate(a, b):
sum_val = a + b
diff = a - b
product = a * b
return sum_val, diff, product
s, d, p = calculate(10, 5) # s=15, d=5, p=50
```
### 3.7 Composition
Composition means using the output of one function as the input to another function.
**Example:**
```
def square(x):
return x * x
def double(x):
return 2 * x
# Composition: double(square(3))
result = double(square(3)) # square(3)=9, double(9)=18
```
### 3.8 Scope of Variables
**Scope** determines where a variable can be accessed in a program.
**Types of Scope:**
1. **Local Scope**: Variables declared inside a function
- Accessible only within that function
- Created when function is called, destroyed when function ends
2. **Global Scope**: Variables declared outside all functions
- Accessible throughout the program
- Exist for the entire program duration
**Example:**
```
x = 10 # Global variable
def my_function():
y = 5 # Local variable
print(x) # Can access global x
print(y) # Can access local y
my_function()
# print(y) # Error! y is not accessible outside function
```
#### 3.8.1 Name Resolution (Resolving Scope of a Name)
Python follows the **LEGB Rule** for name resolution:
- **L** - Local (inside function)
- **E** - Enclosing (in enclosing function, for nested functions)
- **G** - Global (module level)
- **B** - Built-in (Python's built-in names)
**Using `global` keyword:**
To modify a global variable inside a function, use the `global` keyword.
**Example:**
```
count = 0 # Global variable
def increment():
global count # Declare that we want to use global count
count = count + 1
increment()
print(count) # Output: 1
```
### 3.9 Mutable/Immutable Properties of Passed Data Objects
#### 3.9.1 Mutability/Immutability of Arguments/Parameters and Function Calls
**Immutable Objects**: int, float, string, tuple
- When passed to a function, changes inside the function don't affect the original object
- A new object is created if modified
**Mutable Objects**: list, dictionary, set
- When passed to a function, changes inside the function affect the original object
- The same object is modified, not a copy
**Example with Immutable (int):**
```
def modify_number(x):
x = x + 10
print("Inside function:", x)
num = 5
modify_number(num) # Inside function: 15
print("Outside:", num) # Outside: 5 (unchanged)
```
**Example with Mutable (list):**
```
def modify_list(lst):
lst.append(100)
print("Inside function:", lst)
my_list = [1, 2, 3]
modify_list(my_list) # Inside function: [1, 2, 3, 100]
print("Outside:", my_list) # Outside: [1, 2, 3, 100] (changed!)
```
---
## 3. Important Points
- A function must be **defined before** it is called in the program
- Function names follow the same rules as variable names (no spaces, no special characters except underscore)
- The `def` keyword is used to define a function
- Indentation is mandatory in Python functions
- A function can call itself (recursion) or other functions
- The `return` statement immediately exits the function
- A function can have multiple `return` statements but only one will execute
- Parameters with default values must come after parameters without defaults
- Once you use a keyword argument, all following arguments must also be keyword arguments
- Functions help in modular programming and code reusability
- Local variables are destroyed after function execution completes
- Use `global` keyword carefully as it can make debugging difficult
- Mutable objects passed to functions can be modified, affecting the original
- Immutable objects cannot be modified in-place; reassignment creates a new object
---
## 4. Syntax
### Function Definition
```
def function_name(parameter1, parameter2, ...):
"""Docstring explaining what function does"""
# Function body
statement(s)
return value # optional
```
### Function with Default Arguments
```
def function_name(param1, param2=default_value):
# Function body
return value
```
### Function with Multiple Return Values
```
def function_name(parameters):
# Function body
return value1, value2, value3
```
### Using global keyword
```
def function_name():
global variable_name
variable_name = new_value
```
---
## 5. Examples
### Example 1: Simple Function
```
def welcome():
print("Welcome to Python Programming!")
print("Let's learn functions")
welcome() # Function call
```
**Output:**
```
Welcome to Python Programming!
Let's learn functions
```
### Example 2: Function with Parameters
```
def calculate_percentage(marks, total):
percentage = (marks / total) * 100
return percentage
result = calculate_percentage(450, 500)
print(f"Percentage: {result}%")
```
**Output:**
```
Percentage: 90.0%
```
### Example 3: Function with Default Arguments
```
def book_ticket(name, destination, class_type="Economy"):
print(f"Ticket booked for {name}")
print(f"Destination: {destination}")
print(f"Class: {class_type}")
book_ticket("Rahul", "Mumbai")
book_ticket("Priya", "Delhi", "Business")
```
**Output:**
```
Ticket booked for Rahul
Destination: Mumbai
Class: Economy
Ticket booked for Priya
Destination: Delhi
Class: Business
```
### Example 4: Function with Keyword Arguments
```
def student_details(name, roll_no, marks):
print(f"Name: {name}")
print(f"Roll No: {roll_no}")
print(f"Marks: {marks}")
student_details(marks=95, name="Amit", roll_no=25)
```
**Output:**
```
Name: Amit
Roll No: 25
Marks: 95
```
### Example 5: Returning Multiple Values
```
def arithmetic_operations(a, b):
addition = a + b
subtraction = a - b
multiplication = a * b
division = a / b
return addition, subtraction, multiplication, division
add, sub, mul, div = arithmetic_operations(20, 4)
print(f"Addition: {add}")
print(f"Subtraction: {sub}")
print(f"Multiplication: {mul}")
print(f"Division: {div}")
```
**Output:**
```
Addition: 24
Subtraction: 16
Multiplication: 80
Division: 5.0
```
### Example 6: Scope of Variables
```
total_students = 50 # Global variable
def add_student():
global total_students
total_students = total_students + 1
print(f"Inside function: {total_students}")
print(f"Before function call: {total_students}")
add_student()
print(f"After function call: {total_students}")
```
**Output:**
```
Before function call: 50
Inside function: 51
After function call: 51
```
### Example 7: Mutable vs Immutable
```
# Immutable (String)
def change_name(name):
name = "New Name"
print(f"Inside function: {name}")
student_name = "Rahul"
change_name(student_name)
print(f"Outside function: {student_name}")
# Mutable (List)
def add_marks(marks_list):
marks_list.append(85)
print(f"Inside function: {marks_list}")
marks = [70, 80, 90]
add_marks(marks)
print(f"Outside function: {marks}")
```
**Output:**
```
Inside function: New Name
Outside function: Rahul
Inside function: [70, 80, 90, 85]
Outside function: [70, 80, 90, 85]
```
### Example 8: Composition
```
def celsius_to_kelvin(celsius):
return celsius + 273.15
def fahrenheit_to_celsius(fahrenheit):
return (fahrenheit - 32) * 5/9
# Composition: Convert Fahrenheit to Kelvin
temp_f = 98.6
temp_k = celsius_to_kelvin(fahrenheit_to_celsius(temp_f))
print(f"{temp_f}°F = {temp_k}K")
```
**Output:**
```
98.6°F = 310.15K
```
---
## 6. Tables / Diagrams
### Table 1: Types of Arguments
| Argument Type | Description | Example | Rules |
|--------------|-------------|---------|-------|
| **Positional** | Arguments passed in order | `func(10, 20)` | Must match parameter order |
| **Keyword** | Arguments passed by name | `func(a=10, b=20)` | Order doesn't matter |
| **Default** | Parameters with default values | `def func(a, b=10)` | Must be after required parameters |
| **Mixed** | Combination of above | `func(10, b=20)` | Positional first, then keyword |
### Table 2: Scope Comparison
| Feature | Local Variable | Global Variable |
|---------|---------------|-----------------|
| **Declaration** | Inside function | Outside all functions |
| **Accessibility** | Only within function | Throughout program |
| **Lifetime** | During function execution | Entire program runtime |
| **Modification** | Direct | Requires `global` keyword in function |
| **Example** | `def f(): x=5` | `x=5` (outside function) |
### Table 3: Mutable vs Immutable Objects
| Immutable Objects | Mutable Objects |
|------------------|-----------------|
| int | list |
| float | dictionary |
| string | set |
| tuple | bytearray |
| **Cannot be changed** | **Can be changed** |
| Changes create new object | Changes modify same object |
| Safe from unintended modification | Need careful handling in functions |
---
## 7. Common Errors / Misconceptions
### Error 1: Calling function before definition
```
# Wrong
greet() # Error: name 'greet' is not defined
def greet():
print("Hello")
```
**Correct:**
```
def greet():
print("Hello")
greet() # Function called after definition
```
### Error 2: Incorrect number of arguments
```
def add(a, b):
return a + b
result = add(5) # Error: missing 1 required positional argument: 'b'
```
### Error 3: Default parameter before required parameter
```
# Wrong
def student(age=17, name): # SyntaxError
print(name, age)
```
**Correct:**
```
def student(name, age=17): # Required before default
print(name, age)
```
### Error 4: Modifying global variable without `global` keyword
```
count = 0
def increment():
count = count + 1 # UnboundLocalError
increment()
```
**Correct:**
```
count = 0
def increment():
global count
count = count + 1
increment()
print(count) # Output: 1
```
### Error 5: Keyword argument before positional argument
```
def display(name, age, city):
print(name, age, city)
# Wrong
display(name="Rahul", 17, "Delhi") # SyntaxError
```
**Correct:**
```
display("Rahul", 17, city="Delhi") # Positional first, then keyword
```
### Misconception 1: Return statement is mandatory
- **Truth**: Functions without `return` automatically return `None`
- A function can perform actions without returning a value
### Misconception 2: All objects behave the same when passed to functions
- **Truth**: Immutable objects (int, string, tuple) cannot be modified in-place
- Mutable objects (list, dict, set) can be modified and changes reflect outside
### Misconception 3: Variables inside functions are accessible everywhere
- **Truth**: Local variables exist only during function execution
- They are destroyed once function completes
---
## 8. Exam-Oriented Short Notes
### Quick Revision Points
**Function Basics**
- Function = reusable block of code
- Syntax: `def function_name(parameters):`
- Must define before calling
- Use meaningful names
**Arguments and Parameters**
- **Parameter** = variable in definition
- **Argument** = actual value passed
- Types: Positional, Keyword, Default
**Order of Arguments**
1. Positional arguments (required)
2. Keyword arguments
3. Default parameters (in definition)
**Return Statement**
- Sends value back to caller
- Optional; `None` if not specified
- Can return multiple values as tuple
- Exits function immediately
**Scope Rules**
- **Local**: Declared inside function
- **Global**: Declared outside all functions
- Use `global` keyword to modify global variable inside function
- LEGB rule: Local → Enclosing → Global → Built-in
**Mutability**
- **Immutable**: int, float, string, tuple (safe from modification)
- **Mutable**: list, dict, set (can be modified in functions)
**Common Function Patterns**
- No parameters, no return: `def greet():`
- With parameters, no return: `def display(name):`
- No parameters, with return: `def get_value():`
- With parameters and return: `def add(a, b):`
**Important Rules**
- Default parameters must be after required ones
- Keyword arguments must be after positional ones
- Once a keyword argument is used, all following must be keyword
- Function names follow variable naming rules
- Indentation is mandatory
**Benefits of Functions**
- Code reusability
- Modularity
- Easy debugging
- Better organization
- Avoid repetition
---
## Sample Exam Questions & Answers
### Q1: What will be the output?
```
def modify(x, y):
x = x + 10
y.append(10)
a = 5
b = [1, 2, 3]
modify(a, b)
print(a, b)
```
**Answer:** `5 [1, 2, 3, 10]`
- `a` is immutable (int), so changes don't affect original
- `b` is mutable (list), so changes reflect outside
### Q2: Write a function to check if a number is prime.
```
def is_prime(n):
if n <= 1:
return False
for i in range(2, int(n0.5) + 1):
if n % i == 0:
return False
return True
print(is_prime(17)) # True
print(is_prime(10)) # False
```
### Q3: Find and correct the error:
```
def calculate(x, y=10, z):
return x + y + z
```
**Error:** Default parameter `y` before required parameter `z`
**Correct:**
```
def calculate(x, z, y=10):
return x + y + z
```
### Q4: What is the output?
```
x = 10
def func():
x = 20
print(x)
func()
print(x)
```
**Answer:**
```
20
10
```
- Inside function: local `x = 20`
- Outside: global `x = 10` (unchanged)
### Q5: Write a function that returns both quotient and remainder.
```
def divide(dividend, divisor):
quotient = dividend // divisor
remainder = dividend % divisor
return quotient, remainder
q, r = divide(17, 5)
print(f"Quotient: {q}, Remainder: {r}")
```
**Output:** `Quotient: 3, Remainder: 2`