Python Defining Functions
Table of Contents + โ
In the last lesson you learned what functions are and why they matter in Introduction to Functions. You saw the idea of a function. Now you get to make one yourself.
๐ค Why Define Your Own Function?
Say you write three lines of code that print a welcome message. Then you need that same welcome in five different places in your program. So you copy those three lines five times. Now fifteen lines all say the same thing. Change the message once and you have to find and fix all five copies.
That copying is the pain. Defining a function is the cure. You write those lines once and give them a name. After that you can run them by name anytime you want.
So why bother with functions at all? A few plain reasons:
- You avoid repeating the same code. Write it once, call it everywhere.
- You give a piece of logic a name.
calculate_total()reads like English, so the code explains itself. - You can test and fix it in one place. Find a bug? You fix the one function, and every caller gets the fix for free.
๐ณ What โDefiningโ Actually Means
Think of a recipe card. Writing the recipe down is one job. Actually cooking the dish is a different job. You can write a recipe and never cook it. You can also cook it ten times from the one card.
Defining a function is like writing the recipe card. You tell Python โhere are the steps, remember them under this name.โ Python reads them and stores them. It does not run them yet. It just keeps them ready.
Running the function later is like cooking from the card. That part is called calling, and we will get to it in a moment.
๐ ๏ธ The def Syntax, Part by Part
Here is the shape of every function definition in Python. This one takes a name and greets that person.
def greet(name): print("Hello,", name)Let us read def greet(name): piece by piece. Each part has a job:
defis the keyword that tells Python โa function is starting here.โ It is short for define.greetis the function name you pick. You use this name later to run the function. The rules are the same as variable names: lowercase, words joined with underscores.()are the parentheses. Inside them you list the inputs the function expects. Here there is one input calledname. Empty parentheses are fine too when the function needs no input.nameinside the parentheses is a parameter. It is a placeholder for a value you will hand in later.:is the colon. It ends the first line and says โthe body comes next.โ- The indented line below is the body. These are the actual steps Python will run when the function is called.
The colon and the indentation are not decoration. Python uses the indentation to know which lines belong inside the function. Drop the colon or forget to indent, and Python stops with an error. This is the same colon-and-indent rule you already met with if statements and loops.
Note
The body must be indented, usually four spaces. Every line at that same indent is part of the function. The first line that goes back to the left margin is outside the function again.
๐ Defining Is Not Running
Here is the part that surprises people. If you only define a function, nothing prints. The function exists, but you never told Python to run it. Try this.
def greet(name): print("Hello,", name)Output
Nothing. Empty. No greeting. And that is correct.
You only wrote the recipe card. You never cooked from it. Python read the definition, remembered greet, and moved on. To actually run the body, you have to call the function. You do that by writing its name followed by parentheses, and passing in a value.
def greet(name): print("Hello,", name)
greet("Riya")Output
Hello, RiyaThat last line, greet("Riya"), is the call. The name says which function to run. The parentheses say โrun it now.โ And "Riya" is the value you hand in. So defining writes the steps, and calling runs them.
Tip
A quick way to remember it: def greet makes the function exist. greet("Riya") makes the function happen.
๐ Parameters vs Arguments
These two words get mixed up a lot, so let us pin them down. They sound similar but they point at different things.
- A parameter is the name in the definition. It is the placeholder. In
def greet(name):, the parameter isname. - An argument is the real value you pass when you call. In
greet("Riya"), the argument is"Riya".
So the parameter is the empty box, and the argument is what you put in the box. Same function, different arguments each time you call it.
def greet(name): print("Hello,", name)
greet("Riya")greet("Arjun")greet("Alex")Output
Hello, RiyaHello, ArjunHello, AlexSee how name stayed the same in the definition, but the argument changed on each call? That one parameter let the same function greet three different people. That is the whole power of passing values in.
โฉ๏ธ return vs print
Now a really important pair. print and return look like they do the same thing, but they do not. This trips up almost everyone at first, so go slow here.
printjust shows text on the screen. It is for the human looking at the output.returnhands a value back to the code that called the function, so the rest of your program can use it.
Let us see a function that only prints. It shows the result, but it does not give it back.
def add_print(a, b): print(a + b)
result = add_print(2, 3)print("result holds:", result)Output
5result holds: NoneWalk through what happened. add_print(2, 3) printed 5 on its own. But it never returned anything. So when you wrote result = add_print(2, 3), there was no value to store. Python put None in result. None is Pythonโs word for โnothing here.โ That is why the last line says result holds: None.
Now the same idea, but with return instead.
def add_return(a, b): return a + b
result = add_return(2, 3)print("result holds:", result)Output
result holds: 5This time add_return did not print anything by itself. It handed 5 back to the caller. So result actually holds 5, and now you can use it. You can add to it, save it, or pass it into another function.
So here is the rule of thumb:
- Use
printwhen you just want to show something to a person. - Use
returnwhen the value needs to keep living in your program after the function ends.
Caution
A function with no return gives back None. So if you do x = my_function() and x is None, the usual cause is that the function printed the value instead of returning it.
๐ Documenting With a Docstring
When you write a function, it helps to leave a short note saying what it does. Python has a built-in spot for that. A docstring is a triple-quoted string written on the first line inside the function.
Here is a function with a docstring sitting right under the def line.
def area_of_circle(radius): """Return the area of a circle for the given radius.""" return 3.14159 * radius * radius
print(area_of_circle(5))help(area_of_circle)Output
78.53975Help on function area_of_circle in module __main__:
area_of_circle(radius) Return the area of a circle for the given radius.The line """Return the area...""" is the docstring. It does not change what the function does. It is just a note for humans. But Python keeps it, so when someone runs help(area_of_circle), they see exactly what the function is for. Editors and tools read it too. So a one-line docstring is a small habit that pays off later.
๐งฎ A Function That Calculates and Returns
Let us build something real. A shop wants the final price after a discount. We give it the price and the discount percent, and it hands back the amount to pay.
def final_price(price, discount_percent): """Return the price after applying a percentage discount.""" discount = price * discount_percent / 100 return price - discount
to_pay = final_price(1000, 20)print("Pay:", to_pay)Output
Pay: 800.0Read it from the top. final_price takes two parameters, price and discount_percent. Inside, it works out the discount amount, then subtracts it from the price. The return hands the final number back. So to_pay holds 800.0, and you can print it, save it, or run it through more code. Because it returns the value, this function fits into a bigger program. It does not just shout the answer at the screen and forget it.
โ๏ธ A Function That Formats a Message
Functions are great for building text too. Here is one that takes a name and an order number, and returns a tidy confirmation line.
def order_message(name, order_id): """Return a friendly order confirmation message.""" return "Hi " + name + ", your order #" + str(order_id) + " is confirmed."
print(order_message("Riya", 1042))Output
Hi Riya, your order #1042 is confirmed.This function glues the pieces into one sentence and returns it. We used str(order_id) because order_id is a number, and you cannot join a number to text directly. Notice it returns the message instead of printing it. So the caller decides what to do with it. You might print it, send it in an email, or show it on a web page. The function just builds the text. That flexibility is exactly why returning beats printing for most real work.
๐ Calling Again and Again Is the Whole Point
Once a function is defined, you can call it as many times as you like. Each call runs the body again, fresh, with whatever arguments you pass.
def greet(name): print("Hello,", name)
greet("Riya")greet("Arjun")greet("Alex")Output
Hello, RiyaHello, ArjunHello, AlexOne definition, three calls, three greetings. See how you wrote the logic just once? If you ever want to change the wording, you edit the single line inside greet. Every call picks up the new version on its own. No hunting through copies.
๐ท๏ธ Naming Your Functions Well
A function name is the first thing a reader sees, so make it earn its place. A few simple habits:
- Use lowercase letters with underscores between words, like
final_priceororder_message. This is the standard Python style. - Start with a verb when the function does an action, like
greet,calculate_tax, orsave_file. The verb tells the reader what happens. - Say what it does, not how.
area_of_circleis clear.func1tells you nothing.
So a good name reads almost like a sentence at the call site. total = calculate_tax(price) explains itself. You barely need a comment.
๐ Defining vs Calling at a Glance
This small table sums up the two jobs you just learned.
| Action | What you write | What Python does |
|---|---|---|
| Define | def greet(name): then an indented body | Remembers the steps under the name. Runs nothing yet. |
| Call | greet("Riya") | Runs the body now, with the argument you pass. |
โ ๏ธ Common Mistakes
A few small slips trip up almost everyone when they start writing functions.
Forgetting the colon at the end of the def line. Python expects it and stops without it.
# โ Avoid: no colon after the parenthesesdef greet(name) print("Hi", name)
# โ
Good: colon ends the def linedef greet(name): print("Hi", name)Not indenting the body. Python cannot tell which lines belong to the function.
# โ Avoid: body is not indenteddef greet(name):print("Hi", name)
# โ
Good: body is indented under defdef greet(name): print("Hi", name)Defining a function but never calling it, then wondering why nothing happens. The definition alone prints nothing. You have to call it.
# โ Avoid: defined but never called, so nothing runsdef greet(name): print("Hi", name)
# โ
Good: define, then call to actually run itdef greet(name): print("Hi", name)
greet("Riya")Expecting a printed value to come back. If a function only prints, it returns None. So storing it gives you nothing useful.
# โ Avoid: this prints but returns None, so total is Nonedef add(a, b): print(a + b)
total = add(2, 3) # total is None
# โ
Good: return the value so total actually holds itdef add(a, b): return a + b
total = add(2, 3) # total is 5Trying to call the function before it is defined. Python reads top to bottom, so the def has to come first.
# โ Avoid: calling before the function existsgreet("Riya")
def greet(name): print("Hi", name)
# โ
Good: define first, then calldef greet(name): print("Hi", name)
greet("Riya")โ Best Practices
A handful of small habits keep your functions clean and easy to read.
- Pick a name that says what the function does.
show_menutells you far more thanfunc1. - Use a verb in the name when the function performs an action, like
greet,print_total, orsave_file. - Add a short docstring under the
defline so the next person knows what the function is for. - Return a value when the caller needs it, and only print when you truly just want to show something.
- Keep the body focused on one job. A function that does one clear thing is easier to reuse and fix.
- Stick to four spaces for the body indent and stay consistent through the whole file.
๐งฉ What Youโve Learned
A quick recap of what you can now do.
- โ
You can define a function with
def, a name,()with parameters, a:, and an indented body. - โ You know defining only stores the steps. It does not run them until you call.
- โ You can tell a parameter (the placeholder in the definition) from an argument (the real value you pass).
- โ
You know
printshows text, whilereturnhands a value back to the caller, and a function with noreturngivesNone. - โ
You can add a docstring and read it later with
help(). - โ You can name functions clearly and spot the common slips: missing colon, missing indent, expecting a printed value to be returned, and calling before defining.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What does the def keyword do?
Why: def begins a function definition, telling Python to remember the steps under the name you give.
- 2
In def greet(name): ... and the call greet("Riya"), which is the argument?
Why: name is the parameter (the placeholder in the definition). "Riya" is the argument, the real value passed when you call.
- 3
A function only uses print and never return. You write x = the_function(). What does x hold?
Why: print shows text but does not hand a value back. With no return, the function gives None, so x is None.
- 4
Which line is required right after the function name and parentheses?
Why: The def line must end with a colon, which tells Python the indented body comes next.
๐ Whatโs Next?
Right now you pass one or two values into a function. Next you will learn more ways to pass information in, including default values and naming your arguments when you call.