Learn what functions are, how to use them, and the difference between passing by value and passing by reference — with easy, runnable Python code.
A function is a small, reusable block of code that does one specific job. Think of it like a recipe — you write it once, and then you can use it as many times as you want without writing the same code again and again.
Imagine you have a function called make_tea(). Every time you want tea, you don't write the whole recipe — you just say "make_tea" and it does the work. In programming, it works the same way!
# Program to print a message using a function
def greet():
print("Hello! Welcome to Class 10.")
# Function call — it prints the message
greet()
Output:
Hello! Welcome to Class 10.
def greet(): is the function definition (the recipe), and greet() below it is the function call (asking it to do the job).
Every function has these parts:
def keyword — Tells Python "I am creating a function."add, print_msg, greet).def add(a, b):
return a + b
↑ ↑ ↑ ↑
| | | body (the work)
| | parameters (inputs)
| function name
def keyword (starts the function)
int or float. Python figures it out automatically — that's one reason Python is easy to learn!
# Function that adds two numbers and returns the result
def add(a, b):
return a + b
result = add(5, 3)
print("5 + 3 =", result)
Output: 5 + 3 = 8
Python functions can return any type of value. You don't need to declare the type — just use return.
| What it Returns | Example |
|---|---|
| Nothing (like void) | def greet(): print("Hi") |
| A number | def add(a, b): return a + b |
| A string | def shout(w): return w.upper() |
| A list | def nums(): return [1, 2, 3] |
| True or False | def is_even(n): return n % 2 == 0 |
return. If it just does something (like printing), you don't need return — it returns None automatically.
# Find factorial of a number using a function
def factorial(n):
fact = 1
for i in range(1, n + 1):
fact = fact * i
return fact
print("Factorial of 5 =", factorial(5))
Output: Factorial of 5 = 120
In Python, when you pass a number, string, or boolean (called immutable types) to a function, Python sends a copy of the value. The function works on that copy. Whatever happens inside the function does NOT change the original variable.
# Demonstrate that integers don't change outside the function
def triple(x):
x = x * 3 # x is a copy — changes don't go back
print("Inside function: x =", x)
num = 10
print("Before calling: num =", num)
triple(num) # A COPY of num is sent
print("After calling: num =", num)
Output:
Before calling: num = 10
Inside function: x = 30
After calling: num = 10 <-- Original unchanged!
See? The original num stayed 10 because the function only worked on a copy called x.
# Strings are also immutable — changes don't go back
def change_name(name):
name = "Rahul" # reassigns the local copy
print("Inside function: name =", name)
my_name = "Amit"
change_name(my_name)
print("After function: my_name =", my_name)
Output:
Inside function: name = Rahul
After function: my_name = Amit <-- Still "Amit"!
When you pass a list, dictionary, or set (called mutable types) to a function, Python sends a reference to the same object. So if the function modifies it, the original variable DOES change!
# Lists are mutable — changes DO go back
def add_item(items, new_item):
items.append(new_item) # modifies the SAME list
print("Inside function:", items)
fruits = ["apple", "banana"]
print("Before calling:", fruits)
add_item(fruits, "mango")
print("After calling: ", fruits)
Output:
Before calling: ['apple', 'banana']
Inside function: ['apple', 'banana', 'mango']
After calling: ['apple', 'banana', 'mango'] <-- Original changed!
See the difference? Now the original fruits list got updated because lists are mutable.
# Sorting modifies the same list
def sort_list(numbers):
numbers.sort() # sorts in-place
print("Inside function:", numbers)
marks = [45, 12, 78, 34]
sort_list(marks)
print("After sorting: ", marks)
Output:
Inside function: [12, 34, 45, 78]
After sorting: [12, 34, 45, 78] <-- Sorted permanently!
# Using a list to swap — this works because lists are mutable
def swap(pair):
pair[0], pair[1] = pair[1], pair[0] # swap inside the list
data = [7, 4]
print("Before swap:", data)
swap(data)
print("After swap: ", data)
Output:
Before swap: [7, 4]
After swap: [4, 7] <-- Swapped!
| Feature | Pass by Value (Immutable) | Pass by Reference (Mutable) |
|---|---|---|
| What types? | int, float, str, bool, tuple | list, dict, set |
| What is sent? | A copy of the value | Reference to the same object |
| Original changes? | No | Yes (if modified in-place) |
| How to modify? | Cannot modify directly | Use .append(), .sort(), [i] = |
| When to use? | When you don't want original to change | When you want to modify the original |
# What happens when you try to change a number?
def try_change(a, b):
a, b = b, a # swap inside the function
print("Inside function: a =", a, ", b =", b)
x, y = 7, 4
try_change(x, y)
print("After function: x =", x, ", y =", y)
Output:
Inside function: a = 4 , b = 7
After function: x = 7 , y = 4 <-- Swapped inside, but NOT outside!
This proves that integers cannot be changed outside the function. To swap actual variables, you need a workaround like using a list (see Program 8).