Suppose you need to find the average of marks in ten places in your program. You could copy the same four lines ten times. Then the day you find a mistake in the formula, you have to fix it in ten places, and you will miss one. A function solves this. You write the lines once, give them a name, and call that name wherever you need them.
A function is a named block of code that does one job. It runs only when you call it, it can take values in, and it can send a value back. Functions make a program shorter, easier to read and easier to test. Every real Python program, from a small script to a web application, is built from them.
In this tutorial, we explain the three types of functions in Python: built in, user defined and anonymous. We then show how to create and call a function, and go through the four kinds of arguments, which are default, required, keyword and variable length, including *args and **kwargs. We cover lambda functions in detail, and add return values, docstrings, scope, the mutable default trap and recursion. Every example was run on Python 3.13, with its real output.
Introduction to Functions in Python
A function is a group of statements that runs only when it is called. It can take inputs, called parameters, and it can return a result. You use functions to reuse code, to break a large problem into small parts, and to give a clear name to each step.
Reuse. Write the code once, call it many times.
Clarity. A name such as calculate_tax tells the reader what the code does, without reading every line.
Easy fixes. If something is wrong, you fix it in one place.
Testing. A small function with one job is simple to test on its own.
Types of Functions in Python
Types of functions
Type
What it is
Example
Built in
Ready made, comes with Python
print, min, len, sum
User defined
Written by you, with def
def multi(x, y)
Anonymous
A small function with no name, made with lambda
lambda b: b + 30
Built In Functions in Python
Python ships with many functions you can use at once. You have already used print. Here are a few more.
The function bool turns a value into True or False. Zero and empty values give False, and most other values give True.
User Defined Functions in Python
A user defined function is one you write yourself with the def keyword. It is the type you will write most often, and the rest of this tutorial is mostly about it.
Anonymous Functions in Python
An anonymous function has no name and is made with the lambda keyword instead of def. It is limited to one expression, and it is covered in its own section below.
How to Create a Function in Python?
Use the def keyword, then the function name, round brackets with any parameters, and a colon. The lines that belong to the function are indented under it. Write a space after def, because deftest is a syntax error.
Calling a Function
Defining a function does not run it. Nothing prints until you call it. To call a function, write its name followed by round brackets.
python
def test():
print("Python")
return
test()
output
Python
What a Function Returns
A function that has no return line, or only a bare return, gives back a special value called None. You can see it by printing the result of the call:
python
def test():
print("Python")
return
print(test())
output
Python
None
The word Python is printed by the function itself. The word None is the value it returned. To get a useful value back, return it:
python
def multi(x, y):
return x * y
result = multi(12, 5)
print(result)
output
60
Parameters and Arguments
These two words are often mixed up. A parameter is the name in the function definition. An argument is the value you pass when you call it.
python
def greet(name): # name is a parameter
return "Hello, " + name
print(greet("Mithun")) # "Mithun" is an argument
output
Hello, Mithun
Python Function Arguments
Python has four ways to pass arguments. Each one solves a different problem.
Types of arguments
Type
What it does
Default
The parameter has a value, used when the caller leaves it out
Required
The caller must pass it, in the right position
Keyword
The caller passes it by name, in any order
Variable length
The function accepts any number of arguments, with *args or **kwargs
Default Argument
Give a parameter a value with the equals sign. If the caller does not pass one, the default is used. Parameters with defaults must come after the ones without.
python
def multi_default(x, y=5):
return x * y
print(multi_default(x=1))
print(multi_default(x=1, y=3))
print(multi_default(4))
output
5
3
20
The first call uses the default y of 5. The second passes y as 3. The third passes only x, as a plain value, so y is again 5.
Required Arguments
A parameter with no default is required. The caller must pass it, and the values are matched by position, so the first value goes to the first parameter.
python
def multi(x, y):
return x * y
print(multi(12, 5))
output
60
If you leave one out, Python raises an error that names the missing one:
python
def multi(x, y):
return x * y
try:
multi(12)
except TypeError as e:
print("TypeError:", e)
You can pass arguments by name. Then the order does not matter, because Python matches each value to its parameter by the name.
python
def multi(x, y):
return x * y
print(multi(5, 10))
print(multi(x=5, y=10))
print(multi(y=10, x=5))
output
50
50
50
Order matters only with plain values. For a function that divides, the swap changes the answer:
python
def divide(a, b):
return a / b
print(divide(10, 2), divide(b=10, a=2))
output
5.0 0.2
In the second call, a is 2 and b is 10, so the answer is 0.2, even though b was written first. Keyword arguments make calls easier to read, especially when a function has many parameters.
Variable Number of Arguments: *args
Sometimes you do not know how many values will be passed. Put a star before a parameter name, usually args, and Python collects all the extra values into a tuple.
python
def show(*args):
for i in args:
print(i)
show("Variable", "Number", "of", "arguments")
output
Variable
Number
of
arguments
The loop prints each item on its own line. Here is a more useful case, a sum of any number of values, and a check of what args really is:
A lambda function is a small function with no name. It can take any number of arguments, but it has only one expression, and the result of that expression is returned automatically, with no return keyword.
python
lambda arguments: expression
python
x = lambda b: b + 30
print(x(5))
avg = lambda x, y: (x + y) / 2
print(avg(5, 7))
output
35
6.0
Why Use Lambda Functions?
A lambda is best when you need a tiny function for a short time, usually as an argument to another function. It saves you from writing a full def for something used once. Here are three common uses, with sorted, map and filter.
The first line sorts the names without caring about capital letters. The second squares every number. The third keeps only the even numbers. If the logic needs more than one line, write a normal def function instead.
A Lambda Inside Another Function
A function can build and return a lambda. This is how you make a family of related functions.
python
def func1(a):
return lambda b: b * a
double = func1(2)
triple = func1(3)
print(double(11), triple(11))
output
22 33
Calling func1 with 2 gives back a new function that multiplies by 2, and we store it in double. Calling it with 3 gives one that multiplies by 3.
Docstrings: Describe Your Function
A docstring is a short text, in triple quotes, placed as the first line inside a function. It explains what the function does, and Python keeps it so that tools and the help function can show it.
python
def area(length, width):
"""Return the area of a rectangle."""
return length * width
print(area.__doc__)
print(area(4, 5))
output
Return the area of a rectangle.
20
Scope: Local and Global Variables
A variable made inside a function is local. It exists only while the function runs. A variable made outside is global. If a function assigns to a name, Python treats it as a new local variable, and the global one is left alone.
python
counter = 10
def change():
counter = 99 # a new local variable
return counter
print(change(), counter)
output
99 10
The global value is still 10. To change the global one, you must say so with the global keyword. Do this rarely, because it makes code harder to follow. Returning a value is usually cleaner.
This is one of the best known surprises in Python. A default value is made once, when the function is defined, not each time it is called. If the default is a list, every call shares the same list.
The second call still has the apple in it. The fix is to use None as the default, and make the list inside the function.
python
def add_item_safe(item, basket=None):
if basket is None:
basket = []
basket.append(item)
return basket
print(add_item_safe("apple"))
print(add_item_safe("banana"))
output
['apple']
['banana']
Recursion: A Function That Calls Itself
A function can call itself. This is called recursion. It needs a stopping point, called the base case, or it will never end. Factorial is the classic example.
python
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)
print(factorial(5))
output
120
The factorial of 5 is 5 times 4 times 3 times 2 times 1, which is 120. Here, n of 1 or less is the base case.
Functions Are Objects
In Python a function is a value like any other. You can store it in a variable, pass it to another function, or return it, which is what the lambda examples above do.
python
def square(n):
return n * n
operation = square
print(operation(6), operation.__name__)
output
36 square
Common Mistakes With Python Functions
No space after def.deftest is a syntax error. It must be def test.
Lost indentation. The lines inside a function must be indented, or Python raises an IndentationError.
Calling a name that does not exist. Calling plus when you defined multi gives a NameError.
Forgetting the brackets. Writing test without brackets does not call it. It only refers to the function.
Printing instead of returning. A function that only prints gives back None, so you cannot use its result.
Wrong number of arguments. Passing three values to a function with two parameters raises a TypeError.
A list as a default argument. Use None, as shown above.
These are the real messages for the wrong call mistakes:
python
def multi(x, y):
return x * y
try:
plus(5, 10)
except NameError as e:
print("NameError:", e)
try:
multi(1, 2, 3)
except TypeError as e:
print("TypeError:", e)
try:
multi(x=1, z=2)
except TypeError as e:
print("TypeError:", e)
output
NameError: name 'plus' is not defined
TypeError: multi() takes 2 positional arguments but 3 were given
TypeError: multi() got an unexpected keyword argument 'z'
Quick Reference
Functions quick reference
You want to
Write
Define a function
def name(parameters):
Send a value back
return value
Give a parameter a default
def f(x, y=5):
Pass by name
f(x=1, y=3)
Accept any number of values
def f(*args):
Accept any named values
def f(**kwargs):
Make a small unnamed function
lambda b: b + 30
Describe the function
A docstring on the first line
Complete Script to Run Yourself
Here is the full script used to produce every output on this page, in the same order. Copy it into a file, run it with Python 3, and compare the results line by line.
python
# 1. built in functions
print(min(4, 9, 2), max(4, 9, 2), len("Python"), bool(0), bool("hi"))
print(sum([1, 2, 3]), abs(-7), sorted([3, 1, 2]), type(5))
# 2. create and call
def test():
print("Python")
return
test()
# 3. returns None
def test():
print("Python")
return
print(test())
# 4. returns a value
def multi(x, y):
return x * y
result = multi(12, 5)
print(result)
# 5. parameter vs argument
def greet(name): # name is a parameter
return "Hello, " + name
print(greet("Mithun")) # "Mithun" is an argument
# 6. default argument
def multi_default(x, y=5):
return x * y
print(multi_default(x=1))
print(multi_default(x=1, y=3))
print(multi_default(4))
# 7. required arguments
def multi(x, y):
return x * y
print(multi(12, 5))
# 8. missing argument
def multi(x, y):
return x * y
try:
multi(12)
except TypeError as e:
print("TypeError:", e)
# 9. keyword arguments
def multi(x, y):
return x * y
print(multi(5, 10))
print(multi(x=5, y=10))
print(multi(y=10, x=5))
# 10. order with plain values
def divide(a, b):
return a / b
print(divide(10, 2), divide(b=10, a=2))
# 11. *args loop
def show(*args):
for i in args:
print(i)
show("Variable", "Number", "of", "arguments")
# 12. *args sum
def total(*numbers):
return sum(numbers)
def what_type(*args):
return type(args)
print(total(1, 2, 3), total(10, 20, 30, 40), total())
print(what_type(1, 2, 3))
# 13. **kwargs
def profile(**details):
for key, value in details.items():
print(key, "=", value)
profile(name="Asha", city="Kolkata", age=28)
# 14. all together
def order(a, b=2, *args, **kwargs):
print(a, b, args, kwargs)
order(1)
order(1, 3, 4, 5, x=6)
# 15. multiple return values
def min_max(values):
return min(values), max(values)
low, high = min_max([4, 9, 2, 7])
print(low, high, min_max([4, 9, 2, 7]))
# 16. lambda basics
x = lambda b: b + 30
print(x(5))
avg = lambda x, y: (x + y) / 2
print(avg(5, 7))
# 17. lambda with sorted map filter
names = ["Zoya", "amit", "Bina", "chetan"]
print(sorted(names, key=lambda s: s.lower()))
print(list(map(lambda n: n ** 2, [1, 2, 3, 4])))
print(list(filter(lambda n: n % 2 == 0, [1, 2, 3, 4, 5, 6])))
# 18. lambda inside function
def func1(a):
return lambda b: b * a
double = func1(2)
triple = func1(3)
print(double(11), triple(11))
# 19. docstring
def area(length, width):
"""Return the area of a rectangle."""
return length * width
print(area.__doc__)
print(area(4, 5))
# 20. local variable
counter = 10
def change():
counter = 99 # a new local variable
return counter
print(change(), counter)
# 21. global keyword
counter = 10
def change_global():
global counter
counter = 99
change_global()
print(counter)
# 22. mutable default
def add_item(item, basket=[]):
basket.append(item)
return basket
print(add_item("apple"))
print(add_item("banana"))
# 23. safe default
def add_item_safe(item, basket=None):
if basket is None:
basket = []
basket.append(item)
return basket
print(add_item_safe("apple"))
print(add_item_safe("banana"))
# 24. recursion
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)
print(factorial(5))
# 25. functions are objects
def square(n):
return n * n
operation = square
print(operation(6), operation.__name__)
# 26. common errors
def multi(x, y):
return x * y
try:
plus(5, 10)
except NameError as e:
print("NameError:", e)
try:
multi(1, 2, 3)
except TypeError as e:
print("TypeError:", e)
try:
multi(x=1, z=2)
except TypeError as e:
print("TypeError:", e)
Functions are how a script grows into a program. Give each function one job and a clear name, return values instead of printing them, and keep an eye on defaults, scope and indentation. Run the script above, change the arguments, and read the errors, because they teach as much as the successes. Then move on to modules and exception handling, where functions do much of the work.