What Is a Function?
Imagine a vending machine in your college canteen. You put in Rs. 20 (the input), press the button for chai (the instruction), and out comes a cup of chai (the output). The machine does the same thing every time, for anyone who uses it. You do not need to understand the heating coil and the mixing mechanism — you just use it.
A function in Python is the same idea. You write the logic once, give it a name, and then call that name whenever you need the result. The rest of your code does not need to care about how it works internally.
Functions solve two major problems: (1) repetition — you write logic once instead of copying and pasting it everywhere, and (2) organisation — a 200-line program broken into named functions is far easier to read and fix than 200 lines in a single block.
Defining and Calling a Function
Use the def keyword. Everything indented below the def line is the function body. The function does nothing until you call it by name.
# Function with no parameters (no input needed)
def greet():
print("Hello from Quadratech Academy!")
print("Welcome to Python 103.")
# Calling the function:
greet() # Output: Hello from Quadratech Academy! ...
greet() # Call it again — runs the same code again
greet() # And again
Functions with Parameters
Parameters are the inputs your function accepts — like pressing different buttons on the vending machine.
# Function with one parameter
def greet_student(name):
print(f"Hello, {name}! Welcome to Python class.")
greet_student("Arjun") # Hello, Arjun! Welcome to Python class.
greet_student("Meera") # Hello, Meera! Welcome to Python class.
# Function with multiple parameters and a return value
def add(a, b):
result = a + b
return result # Send the answer back to whoever called us
total = add(15, 27)
print(total) # 42
A Real Example — Percentage Calculator
def calculate_percentage(obtained, total):
if total == 0:
return 0 # Avoid division by zero
percentage = (obtained / total) * 100
return round(percentage, 2) # round to 2 decimal places
# Use it for different students:
print(calculate_percentage(427, 500)) # 85.4
print(calculate_percentage(312, 400)) # 78.0
print(calculate_percentage(180, 600)) # 30.0
Write a function called is_prime(n) that returns True if n is a prime number and False if it is not. Then use a for loop with range(2, 50) and call your function to print all prime numbers between 2 and 49.
Parameters and Return Values
Functions become much more powerful when you understand the different ways to pass inputs and get outputs back.
Keyword Arguments
Normally you pass arguments in order. With keyword arguments, you name them — so order doesn't matter and the code is self-documenting.
def display_student(name, branch, year):
print(f"Name: {name} | Branch: {branch} | Year: {year}")
# Positional — must be in the right order
display_student("Ravi", "ECE", 3)
# Keyword — order doesn't matter
display_student(branch="CSE", year=2, name="Sneha")
Default Parameter Values
Set a default value for a parameter. If the caller doesn't provide it, the default is used. Like a photocopy shop — if you don't specify single-sided or double-sided, they default to single-sided.
def calculate_cgpa(marks_list, scale=10):
# scale defaults to 10 if not provided
total = sum(marks_list)
out_of = len(marks_list) * scale
return round((total / out_of) * scale, 2)
# 10-point scale (uses default)
print(calculate_cgpa([8, 7, 9, 8, 7])) # 7.8
# 4-point scale (overrides default)
print(calculate_cgpa([3.5, 3.7, 4.0], scale=4)) # 3.73
Returning Multiple Values
Python functions can return multiple values as a tuple. Unpack them directly into separate variables.
def area_and_perimeter_rectangle(length, width):
area = length * width
perimeter = 2 * (length + width)
return area, perimeter # Python packs these as a tuple
# Unpack both return values at once:
a, p = area_and_perimeter_rectangle(8, 5)
print(f"Area: {a} sq units") # Area: 40 sq units
print(f"Perimeter: {p} units") # Perimeter: 26 units
Area Calculators — A Complete Example
import math # We'll cover this properly in the Modules section
def area_circle(radius):
return round(math.pi * radius ** 2, 4)
def area_rectangle(length, width):
return length * width
def area_triangle(base, height):
return 0.5 * base * height
# Use them all:
print("Circle (r=7):", area_circle(7)) # 153.9380
print("Rectangle (4x6):", area_rectangle(4, 6)) # 24
print("Triangle (b=10,h=8):", area_triangle(10, 8)) # 40.0
A function without a return statement returns None by default. If you write result = my_function() and the function only prints the answer instead of returning it, result will be None. Always decide: should this function print the answer, or return it so the caller can use it?
Scope — Who Can See What?
Think about your college. Some information is private to your classroom — the attendance register only your class teacher has. Some information the whole college can see — the notice board. Variables in Python work the same way. Where you create a variable determines who can access it.
Local Scope — Inside the Classroom
A variable created inside a function exists only while that function is running. Once the function finishes, the variable is gone. Other functions cannot see it.
def calculate_tax(income):
tax_rate = 0.20 # local variable — only visible inside this function
tax = income * tax_rate
return tax
result = calculate_tax(50000)
print(result) # 10000.0
# This would cause an error:
# print(tax_rate) # NameError: name 'tax_rate' is not defined
Global Scope — The Notice Board
A variable created outside all functions is global — every function can read it. But to modify it inside a function, you need to declare it with the global keyword.
passing_marks = 40 # global variable — everyone can read this
def check_result(marks):
if marks >= passing_marks: # reading global variable — fine
return "PASS"
return "FAIL"
print(check_result(55)) # PASS
print(check_result(32)) # FAIL
# Modifying a global variable:
student_count = 0
def register_student():
global student_count # tell Python we mean the global one
student_count += 1
register_student()
register_student()
register_student()
print("Students registered:", student_count) # 3
Scope prevents functions from accidentally overwriting each other's variables. If every variable were global, a bug in one function could corrupt data used by another function — and tracking down such bugs is a nightmare. Keep variables as local as possible. Only use global when you genuinely need shared state across multiple functions.
If you create a local variable with the same name as a global one, Python uses the local version inside the function. The global is untouched. This is called "shadowing" and can cause confusing behaviour. Example: if marks = 90 globally and you write marks = 50 inside a function (without global), the global stays 90. Use distinct names to avoid confusion.
Modules — Borrowing Other People's Work
When an electrician comes to fix wiring in your house, they don't manufacture their own screwdrivers and wire cutters from scratch. They go to the hardware shop and pick up the tools they need. Python has a massive hardware shop called its standard library — hundreds of modules (collections of pre-written functions) ready for you to import and use.
import math — Mathematics Done Right
import math print(math.pi) # 3.141592653589793 print(math.e) # 2.718281828459045 (Euler's number) print(math.sqrt(144)) # 12.0 — square root print(math.pow(2, 10)) # 1024.0 — 2 to the power 10 print(math.floor(9.7)) # 9 — round down print(math.ceil(9.2)) # 10 — round up print(math.factorial(5)) # 120 — 5! = 5×4×3×2×1 print(math.log(100, 10)) # 2.0 — log base 10 of 100 # Trigonometry (angles in radians): angle_degrees = 30 angle_radians = math.radians(angle_degrees) print(math.sin(angle_radians)) # 0.5 print(math.cos(angle_radians)) # 0.866...
import random — Randomness for Simulations and Games
import random
# Random integer between 1 and 6 (like a dice roll):
dice = random.randint(1, 6)
print("Dice:", dice)
# Random float between 0 and 1:
probability = random.random()
print("Probability:", probability)
# Pick a random item from a list:
students = ["Arjun", "Meera", "Ravi", "Sneha", "Kiran"]
selected = random.choice(students)
print("Today's presenter:", selected)
# Shuffle a list in place (like shuffling a deck of cards):
random.shuffle(students)
print("New order:", students)
import datetime — Working with Dates and Times
import datetime
now = datetime.datetime.now()
print("Current date and time:", now)
print("Year:", now.year)
print("Month:", now.month)
print("Day:", now.day)
print("Hour:", now.hour)
# Format date as a readable string:
formatted = now.strftime("%d %B %Y, %I:%M %p")
print("Formatted:", formatted) # e.g. 08 May 2026, 10:30 AM
# Calculate how many days until an event:
exam_date = datetime.date(2026, 6, 15)
today = datetime.date.today()
days_left = (exam_date - today).days
print(f"Days until exam: {days_left}")
from module import function — Import Specific Things
Instead of importing the whole module and typing math.sqrt(), you can import just the function you need and call it directly.
from math import sqrt, pi, sin, cos, radians
# Now use them directly without the "math." prefix:
print(sqrt(256)) # 16.0
print(pi) # 3.141592653589793
print(sin(radians(90))) # 1.0
# You can also give imports an alias:
from datetime import datetime as dt
print(dt.now().strftime("%H:%M")) # Current time like "14:35"
Build a function called scientific_calc() that asks the user to choose an operation (sqrt, power, sin, cos, log) and the required input(s), then prints the result using the math module. Wrap the whole thing in a while True loop with an "Exit" option.
Creating Your Own Module
Here is where it all comes together. Instead of copying your useful functions into every new project, you can save them in a separate .py file and import them exactly like you import math or random.
Step 1 — Create the Module File
Save this as quadratech_utils.py in the same folder as your main program.
# quadratech_utils.py
# A collection of useful academic helper functions
def calculate_percentage(obtained, total):
"""Calculate percentage from marks obtained and total marks."""
if total == 0:
return 0.0
return round((obtained / total) * 100, 2)
def grade_from_marks(percentage):
"""Return letter grade from a percentage score."""
if percentage >= 90:
return "A+"
elif percentage >= 80:
return "A"
elif percentage >= 70:
return "B"
elif percentage >= 60:
return "C"
elif percentage >= 40:
return "D"
else:
return "F"
def cgpa_to_percentage(cgpa, scale=10):
"""Convert CGPA on a given scale to percentage.
Common formula used by many Indian universities:
percentage = (CGPA / scale) * 100
For some universities: percentage = CGPA * 9.5
"""
return round((cgpa / scale) * 100, 2)
def is_passed(percentage, passing_percentage=40):
"""Check if a student has passed based on their percentage."""
return percentage >= passing_percentage
# This block only runs when you execute THIS file directly,
# not when you import it from somewhere else:
if __name__ == "__main__":
print("Testing quadratech_utils module...")
print(calculate_percentage(427, 500)) # 85.4
print(grade_from_marks(85.4)) # A
print(cgpa_to_percentage(8.5)) # 85.0
print(is_passed(85.4)) # True
print(is_passed(35.0)) # False
print("All tests passed.")
Step 2 — Import and Use Your Module
Now in your main program file (in the same folder), import it:
import quadratech_utils as qt # import with a short alias
# Process results for a class of students:
class_results = [
{"name": "Arjun", "obtained": 427, "total": 500},
{"name": "Meera", "obtained": 312, "total": 500},
{"name": "Ravi", "obtained": 189, "total": 500},
{"name": "Sneha", "obtained": 461, "total": 500},
]
print("=" * 50)
print(f"{'Name':<12} {'%':>6} {'Grade':>6} {'Status':>8}")
print("=" * 50)
for student in class_results:
pct = qt.calculate_percentage(student["obtained"], student["total"])
grade = qt.grade_from_marks(pct)
status = "PASS" if qt.is_passed(pct) else "FAIL"
print(f"{student['name']:<12} {pct:>6.1f} {grade:>6} {status:>8}")
print("=" * 50)
The __name__ == "__main__" Pattern Explained
When Python runs a file directly, it sets a special variable __name__ to the string "__main__". When Python imports that file as a module, __name__ is set to the file's name instead.
The if __name__ == "__main__": guard lets you write test code inside your module file that only runs when you execute the file directly. When someone imports your module, the guard code is skipped — which is the correct behaviour. Every module you create should have this guard.
Add a function called cgpa_to_percentage_anna(cgpa) to quadratech_utils.py that uses Anna University's formula: percentage = cgpa * 10 - 0.75 * (10 - cgpa). Then add a function sgpa_to_cgpa(sgpa_list) that takes a list of semester GPAs and returns the overall CGPA as their average. Test both in the if __name__ == "__main__" block.
You now know variables, data types, operators, if/else, loops, lists, functions, scope, and modules. That is the complete foundation. You can write real, useful programs. The next step is to apply it in a real engineering context — Python for data analysis, sensor processing, or automation.
