AiTechWorlds
AiTechWorlds
Before food magazines existed, cooks kept their recipes secret, writing them down only for family members. Imagine a grandmother who makes the world's best chocolate cake. Every time a family member wants to make it, they call her up, she dictates the recipe from memory, and they write it down again.
One day, someone has the brilliant idea: write the recipe once, give it a name, and share it with everyone. Now nobody needs to call grandma. They just pull out the recipe card labeled "Chocolate Cake", follow the steps, and the cake appears.
That recipe card is a function.
You define it once. You name it. Whenever you want the result — you call it by name. The instructions run, the result appears. You never need to rewrite the recipe. You could make 10 cakes in a day and the recipe stays the same card.
This is the most important concept in all of programming: the idea of packaging logic into a named, reusable unit.
A function is a named block of code that performs a specific task. You write it once (the definition), and you can call it as many times as you need.
In Python, you've already been using functions — you just might not have realized it:
print("hello") — a built-in function that displays textlen("hello") — a built-in function that counts charactersint("42") — a built-in function that converts text to integertype(3.14) — a built-in function that returns the type of a valuePython comes with hundreds of built-in functions. But the real power comes from defining your own.
DRY stands for Don't Repeat Yourself. It's one of the golden rules of good programming.
Here's the problem without functions. Suppose you're building a program that converts temperatures in three places:
# Without functions — repetition everywhere
temp1 = 100
fahrenheit1 = (temp1 * 9/5) + 32
print(f"{temp1}°C = {fahrenheit1}°F")
temp2 = 37
fahrenheit2 = (temp2 * 9/5) + 32
print(f"{temp2}°C = {fahrenheit2}°F")
temp3 = 0
fahrenheit3 = (temp3 * 9/5) + 32
print(f"{temp3}°C = {fahrenheit3}°F")
The formula (temp * 9/5) + 32 appears three times. What if the formula had a bug? You'd need to fix it in three places — and remember to find all three. What if it appeared 20 times across your program? This is how bugs multiply and maintenance becomes a nightmare.
Syntax:
def function_name():
# code goes here
# indented 4 spaces
def is the keyword that starts a function definitionfunction_name is what you'll use to call it (follow the same naming rules as variables: lowercase, underscores for spaces): ends the header lineSimplest possible function:
def greet():
print("Hello! Welcome to Python.")
# Calling the function
greet()
greet()
greet()
Output:
Hello! Welcome to Python.
Hello! Welcome to Python.
Hello! Welcome to Python.
You wrote the greeting logic once. You called it three times. One definition, unlimited use.
| Type | Examples | Who wrote it? |
|---|---|---|
| Built-in | print(), len(), int(), type(), range(), input() | Python's creators |
| User-defined | greet(), calculate_pay(), convert_temp() | You |
Built-in functions are baked into Python — they're always available. User-defined functions are ones you write to solve your specific problems.
| Without Functions | With Functions |
|---|---|
| Same logic repeated in multiple places | Logic written once, called anywhere |
| Fix a bug in N places | Fix a bug in 1 place |
| Hard to read and follow | Self-documenting — the function name describes what it does |
| Hard to test individual pieces | Each function can be tested independently |
| Gets messy as programs grow | Stays organized at any scale |
Instead of scattering the formula everywhere, let's package each conversion into its own clearly named function.
def celsius_to_fahrenheit(celsius):
fahrenheit = (celsius * 9/5) + 32
return fahrenheit
def fahrenheit_to_celsius(fahrenheit):
celsius = (fahrenheit - 32) * 5/9
return celsius
def kelvin_to_celsius(kelvin):
return kelvin - 273.15
# Using the functions
temp_c = 100
print(f"{temp_c}°C = {celsius_to_fahrenheit(temp_c)}°F")
print(f"Water boils at {celsius_to_fahrenheit(100)}°F")
print(f"Body temperature: {celsius_to_fahrenheit(37)}°F")
What each line does:
def celsius_to_fahrenheit(celsius): — defines a function named celsius_to_fahrenheit that accepts one input called celsiusfahrenheit = (celsius * 9/5) + 32 — applies the conversion formula; stores result in a local variablereturn fahrenheit — sends the result back to whoever called the functioncelsius_to_fahrenheit(temp_c) — calls the function with temp_c as the input; the function runs and hands back a valueprint f-string uses that returned value directlyOutput:
100°C = 212.0°F
Water boils at 212.0°F
Body temperature: 98.6°F
Now if a scientist tells you the formula was slightly wrong, you fix it in one place — the function definition — and every single call to that function is automatically corrected.
return?return sends a value out of the function back to the code that called it.
def add(a, b):
return a + b
result = add(3, 7)
print(result) # 10
Without return, the calculation happens inside the function but the result disappears — like doing math on a whiteboard and then erasing it without writing the answer anywhere.
Functions that don't have a return statement still return something: the special value None, which means "nothing." This is fine for functions whose job is to do something (like print) rather than calculate something.
You call a function by writing its name followed by parentheses:
function_name() # no inputs
function_name(value) # with one input
function_name(a, b, c) # with multiple inputs
The function runs, does its work, and (if it has a return) hands a value back.
def, call anywhere with the function's namereturn sends a result back to the caller; without it, the function returns Noneprint, len, int); you add your own user-defined functionscelsius_to_fahrenheit(37) is self-explanatoryNext lesson: Parameters and return values — how to pass information into functions and get results back out.
Get this course's notes on Telegram!
Free cheat sheets, summaries & practice exercises