You define a function in Python with the def keyword: write def, the function name, parentheses with any parameters, and a colon. Then indent the body underneath. The function doesn’t run until you call it by name with parentheses:
def greet(name):
return f"Hello, {name}!"
print(greet("Megan")) # Hello, Megan!
Each Output label below holds text pasted straight from my Windows console, where the interpreter was Python 3.12.5.
In this tutorial, we’ll build a first function from scratch, then cover the parts of a def statement, naming rules, parameters, return values, calling, docstrings, type hints and placeholder functions.
Build your first Python function step by step
A function is a named block of code you can run again and again. Python ships with plenty of built-in functions like print() and len(); def lets you add your own. Here’s the whole process for a first-timer:
- Create a folder for your practice files, for example
C:\pyguides. - Open Notepad or VS Code and paste the code below.
- Save it as
first_function.pyin that folder. In Notepad, set Save as type to All files so it doesn’t become.py.txt. - Press Win + R, type
cmdand press Enter to open Command Prompt. - Run
cd C:\pyguides, thenpython first_function.py.
def greet_customer(name):
"""Return a short welcome message for one customer."""
return f"Welcome to the Austin store, {name}!"
print("Script started")
message = greet_customer("Megan")
print(message)
print(greet_customer("Alex"))
Output:
Script started
Welcome to the Austin store, Megan!
Welcome to the Austin store, Alex!

Notice the order. Python reads the def block and stores the function without running it. Only the two calls at the bottom produce the welcome lines.
If python isn’t recognized, reinstall Python and tick Add python.exe to PATH on the first installer screen, or try the py launcher instead.
What are the parts of a Python def statement?
Every function definition has the same pieces. Here’s a small one that calculates an order line, with each part labeled:
def order_total(price, quantity):
"""Return the total cost of an order line."""
total = price * quantity
return total
print(order_total(12.50, 4))
print(type(order_total))
print(order_total.__name__)
Output:
50.0
<class 'function'>
order_total
| Part | In the example | What it does |
|---|---|---|
def keyword | def | Tells Python a function definition starts here |
| Name | order_total | The label you use to call it later |
| Parameters | (price, quantity) | Placeholders for the values you pass in; can be empty |
| Colon | : | Ends the header line; leaving it out is a SyntaxError |
| Docstring | """Return the total...""" | Optional description shown by help() |
| Indented body | total = ... | The code that runs on each call, indented 4 spaces |
return | return total | Sends a value back to the caller |
The output also shows that a function is an object of type function with its own __name__. That matters later when you pass functions around.
The body ends where the indentation stops. Mixing tabs and spaces raises an IndentationError, so let your editor insert spaces. A function with no return line still works; it’s what people call a void function in Python.
Python function naming rules and conventions
A function name follows the same rules as a variable name. It can hold letters, digits and underscores, can’t start with a digit, and can’t be a reserved keyword such as class or return. This script checks a few candidates:
import keyword
for name in ("calculate_tax", "Calculate_Tax", "_helper", "class", "return", "total2"):
ok = name.isidentifier() and not keyword.iskeyword(name)
print(f"{name:<15} valid function name: {ok}")
Output:
calculate_tax valid function name: True
Calculate_Tax valid function name: True
_helper valid function name: True
class valid function name: False
return valid function name: False
total2 valid function name: True
Calculate_Tax is legal, but PEP 8, Python’s style guide, asks for lowercase words joined by underscores (snake_case). A leading underscore like _helper is a hint that the function is meant for internal use.
Break the digit rule and Python refuses to run the file at all, before any line executes:
def 2nd_total(price):
return price * 2
Output:
File "C:\pyguides\bad_name.py", line 1
def 2nd_total(price):
^
SyntaxError: invalid decimal literal
I name functions with a verb first, like calculate_tax or send_invoice. Reading the call then tells you what happens.
Add parameters and arguments to a Python function
Parameters are the names in the definition; arguments are the values you pass when you call. You can pass arguments by position, by keyword, or skip ones that have a default value:
def shipping_quote(weight_lb, zone, express=False):
rate = 4.25 if zone == "local" else 7.80
cost = rate + weight_lb * 0.65
if express:
cost += 12.00
return f"${cost:.2f}"
print(shipping_quote(3, "local")) # positional
print(shipping_quote(zone="national", weight_lb=10)) # keyword, any order
print(shipping_quote(10, "national", express=True)) # default overridden
try:
shipping_quote(3)
except TypeError as err:
print("TypeError:", err)
Output:
$6.20
$14.30
$26.30
TypeError: shipping_quote() missing 1 required positional argument: 'zone'
Keyword arguments make calls easier to read and let you change the order. Put parameters with defaults after the required ones. More patterns are in Python functions with optional arguments.
Leaving out a required argument raises a TypeError that names the missing parameter, as the last line shows. When you don’t know how many values will arrive, see the difference between *args and **kwargs.
How do you return values from a Python function?
return ends the function and hands a value back. If a function has no return, or a bare return, the caller gets None:
def apply_discount(price, pct):
return round(price * (1 - pct / 100), 2)
def log_sale(item):
print(f"Logged sale: {item}")
def price_range(prices):
return min(prices), max(prices)
print(apply_discount(80.00, 15))
result = log_sale("Desk lamp")
print("log_sale returned:", result)
low, high = price_range([19.99, 4.50, 32.00])
print(f"Cheapest ${low:.2f}, priciest ${high:.2f}")
Output:
68.0
Logged sale: Desk lamp
log_sale returned: None
Cheapest $4.50, priciest $32.00
log_sale() prints but returns nothing, so result holds None. The Python return statement guide covers early exits and returning inside loops.
price_range() returns two values packed into a tuple, which I unpack into low and high. Here’s more on how to return multiple values from a function.
Prefer returning a value over printing it inside the function. A returned number can be stored, tested, formatted or passed to another function; a printed one is gone.
How do you call a function in Python?
Defining and calling go together. To call a function, write its name followed by parentheses, with any arguments inside. You can print the result, store it in a variable, or call it once per item in a loop:
def to_fahrenheit(celsius):
return celsius * 9 / 5 + 32
print(to_fahrenheit(25)) # call and print right away
reading = to_fahrenheit(30.5) # call and keep the result
print("Stored:", reading)
for c in (0, 18, 37): # call it once per item
print(c, "C =", to_fahrenheit(c), "F")
print(to_fahrenheit) # no parentheses: the function object
convert = to_fahrenheit # functions are values
print(convert(100))
Output:
77.0
Stored: 86.9
0 C = 32.0 F
18 C = 64.4 F
37 C = 98.6 F
<function to_fahrenheit at 0x000001DF7013A340>
212.0

The <function to_fahrenheit at 0x...> line is the classic beginner slip. to_fahrenheit without parentheses doesn’t run anything; it just refers to the function object. Add the parentheses and it runs.
Because a function is a value, convert = to_fahrenheit gives the same function a second name. That’s also how one function can call a function within another function.
Once your helpers live in their own file, import them; this guide shows how to call a function from another file. A function that’s only one expression can also be a lambda function.
Why must you define a function before calling it?
Python runs a script from top to bottom. A def line creates the function name when Python reaches it, so calling the name earlier fails:
print("Before the call")
print(sales_tax(100.00))
def sales_tax(amount):
return round(amount * 0.0825, 2)
Output:
Before the call
Traceback (most recent call last):
File "C:\pyguides\define_before_call.py", line 2, in <module>
print(sales_tax(100.00))
^^^^^^^^^
NameError: name 'sales_tax' is not defined

sales_tax stops the script with a NameError because the def hasn’t run yet.The fix is to move the def above the call. If you see this error for other names, the NameError: name is not defined guide lists the usual causes.
There’s one subtlety. Inside a function body, names are looked up when the function runs, not when it’s defined. So checkout() can mention sales_tax() before it exists, as long as both are defined before the call:
def checkout(amount):
return amount + sales_tax(amount) # sales_tax is looked up when checkout runs
def sales_tax(amount):
return round(amount * 0.0825, 2)
print(checkout(100.00))
Output:
108.25
That’s why many scripts put all the def blocks first and the calls at the very bottom.
Document a Python function with a docstring and type hints
A docstring is a string literal on the first line of the body. Python stores it in __doc__, and help(function_name) displays it. Type hints label what each parameter and the return value should be:
def monthly_payment(principal: float, annual_rate: float, months: int = 12) -> float:
"""Return the fixed monthly payment for a simple loan.
principal: amount borrowed in USD
annual_rate: yearly interest rate, for example 0.06 for 6%
"""
r = annual_rate / 12
return round(principal * r / (1 - (1 + r) ** -months), 2)
print(monthly_payment(5000, 0.06, 24))
print(monthly_payment.__doc__.splitlines()[0])
print(monthly_payment.__annotations__)
print(monthly_payment(5000, 0.06, months=36)) # an int works fine for a float hint
Output:
221.6
Return the fixed monthly payment for a simple loan.
{'principal': <class 'float'>, 'annual_rate': <class 'float'>, 'months': <class 'int'>, 'return': <class 'float'>}
152.11
The : float and -> float parts are type hints. They’re stored in __annotations__ and help editors and tools like mypy, but Python doesn’t enforce them when the code runs.
Hints also work with containers; see type hints for tuples. I add a one-line docstring to every function I share, and a longer one when the parameters need explaining.
Write a placeholder Python function with pass
Sometimes you know a function’s name and parameters before you know its body. A body can’t be empty, so use pass or ... as a placeholder:
def send_invoice(customer):
pass # TODO: write this next week
def refund_order(order_id):
... # Ellipsis works as a placeholder too
print(send_invoice("Adele Vance"))
print(refund_order(1042))
Output:
None
None
Both stubs run and return None, which lets you sketch a program’s structure first. The Python pass statement page has more on where pass fits.
Example: build a checkout receipt from small Python functions
Here’s how the pieces fit in a real script. Each function does one job: add up the cart, work out tax, print the receipt. A main() function ties them together:
TAX_RATE = 0.0825 # Texas state sales tax
def subtotal(cart):
"""Add up price * quantity for each line."""
return sum(price * qty for _, price, qty in cart)
def sales_tax(amount, rate=TAX_RATE):
return round(amount * rate, 2)
def print_receipt(customer, cart):
sub = subtotal(cart)
tax = sales_tax(sub)
print(f"Receipt for {customer} - October 20, 2026")
for item, price, qty in cart:
print(f" {item:<14} {qty} x ${price:>6.2f}")
print(f" Subtotal: ${sub:,.2f}")
print(f" Tax (8.25%): ${tax:,.2f}")
print(f" Total: ${sub + tax:,.2f}")
def main():
cart = [("Coffee beans", 14.99, 2), ("Travel mug", 22.50, 1), ("Filters", 4.25, 3)]
print_receipt("Alex Wilber", cart)
main()
Output:
Receipt for Alex Wilber - October 20, 2026
Coffee beans 2 x $ 14.99
Travel mug 1 x $ 22.50
Filters 3 x $ 4.25
Subtotal: $65.23
Tax (8.25%): $5.38
Total: $70.61

TAX_RATE sits outside the functions, so every function can read it; Python variable scope explains which names a function can see and change.
Wrapping the calls in main() keeps the top level clean. If you’d like to pass values from the command line, see the Python main function with arguments.
Splitting work this way means you can test sales_tax(100) on its own and reuse it on the next project.
With your first functions working, these tutorials take the next step:
- Functions vs methods in Python
- Call a function by its string name
- Exit a function early in Python
- Keep a value between calls with static variables
Frequently asked questions
What keyword defines a function in Python?
The def keyword, followed by the name, parentheses and a colon. The indented lines below form the body.
Does defining a function run it?
No. def only creates the function. The body runs each time you call it with parentheses, like greet("Megan").
Can a Python function have no parameters?
Yes. Use empty parentheses, as in def main():, and call it with main().
What does a function return if there’s no return statement?
It returns None. A bare return also returns None.
Why do I get NameError when I call my function?
The call runs before the def line, or the name is misspelled. Move the definition above the call.
Where is defining functions documented?
See Defining Functions in the official Python tutorial.

Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn