CSIP12.in
Back to List
Calculating...
UNIT 1 : CH 3 Dec 09, 2025

Working with Python Function

## 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`