These notes walk you through Python functions in the order most readers need: how to define one, pass data in, return results, and use *args / **kwargs. Later sections touch docstrings, scope, lambdas, and how built-ins relate to your own def functions.
def greet():
print("Hello, Python!")
greet()Running that prints a single line, Hello, Python!. A function is a reusable block of code: you introduce it with def, give it a name, and run it by writing the name followed by parentheses. Everything below stays on defining and calling your own functions—parameters, return, defaults, and *args / **kwargs.
Tested on: Python 3.13.3; kernel 6.14.0-37-generic.
What is a function in Python?
A function groups statements so you can call them by name instead of copying logic. Benefits stay the same as always: less duplication, clearer names for chunks of work, and one place to fix bugs. You are not required to return a value; callers still get None back when there is no return.
Python function syntax
The header is def name(parameters): and the body is indented. Parameters live in parentheses; an empty pair means “no inputs.” The colon is mandatory. Names follow the usual identifier rules (letters, digits, underscores; cannot start with a digit).
Forgetting the colon after the parentheses produces a syntax error before any body code runs:
File "<stdin>", line 1
def broken()
^
SyntaxError: expected ':'Fix the header (def broken():), then ensure every line in the body is indented consistently under def.
Create a simple function in Python
The smallest useful function has a def line and an indented body. This is the same idea as the opening greet example: no parameters, one action.
def line_dashes():
print("-" * 40)
line_dashes()You should see a row of forty hyphen characters. Everything indented under def belongs to the function until a line dedents back to the same level as def.
Call a function in Python
Use the function name plus (). Leaving the parentheses off passes the function object itself without running it—useful for callbacks, but not what you want when you intend to execute the body.
def ping():
print("pong")
ping()
obj = ping
print(obj is ping)The first call prints pong. The comparison prints True because obj and ping refer to the same function; obj() would also print pong.
Function with parameters
Parameters declare the inputs the caller must supply (unless defaults cover them). Parameters are the names in the definition; arguments are the expressions you pass at the call site.
def area(length, width):
return length * width
print(area(4, 5))That prints 20. Positional arguments map to parameters in left-to-right order, so swapping 4 and 5 still multiplies two numbers but might violate the meaning of length vs width in real code—name parameters clearly and document order-sensitive APIs.
Function with return value
return hands a value back to the caller and ends the function immediately. Any code after return in the same block does not run.
def double(x):
return x * 2
print(double(3))Output is 6. If you omit return, the function completes and the call expression evaluates to None.
Function returning multiple values
Comma-separated values are packed into a tuple. Callers unpack into names or treat the result as one tuple. See Python return multiple values for the full pattern.
def min_max(values):
return min(values), max(values)
low, high = min_max([3, 1, 4])
print(low, high)That prints 1 4.
Function with default arguments
Defaults make parameters optional. Defaults are evaluated once, when the function is defined—never use a mutable literal like [] or {} as a default unless you intend sharing across calls.
def power(base, exp=2):
return base**exp
print(power(3))
print(power(3, 3))First line prints 9, second prints 27.
Function with keyword arguments
Keyword arguments pass name=value so order does not matter among those parameters. They pair well with longer signatures and defaults.
def divide(*, dividend, divisor):
return dividend / divisor
print(divide(divisor=2, dividend=10))Keyword-only parameters (the * marker before dividend) force callers to use names, which prevents accidental argument swaps.
Function with *args
A parameter starting with * collects extra positional arguments into a tuple; see Python tuple if you want a refresher on that type. The name args is convention only.
def total(*numbers):
return sum(numbers)
print(total(1, 2, 3))Output is 6. Normal parameters may appear before *args; only one * splat parameter is allowed in that position class.
Function with kwargs
A parameter starting with ** collects extra keyword arguments into a dictionary. Typical order is normal parameters, then *args (if any), then **kwargs. See Python *args and **kwargs for forwarding and iteration patterns beyond this overview.
def print_user(**kwargs):
for key, value in kwargs.items():
print(key, value)
print_user(name="Alice", age=30)You should see two lines: name Alice and age 30 (order follows the mapping’s iteration order, which matches insertion for built-in dicts in recent Python).
Local and global variables in functions
Assignment to a simple name inside a function makes it local unless you declare global or nonlocal. Reading a global name works without global, but rebinding requires the keyword—otherwise Python creates a local that shadows the outer name. For patterns, pitfalls, and the global keyword, read Global variables in Python.
count = 0
def bump():
global count
count += 1
bump()
print(count)That prints 1.
Function with docstring
A docstring is a string literal immediately after the def line; tools like help() display it. Keep the first line imperative and short.
def add(a, b):
"""Return the sum of two numbers."""
return a + b
print(add.__doc__.strip())You should see Return the sum of two numbers.
Lambda function in Python
Lambdas are small anonymous functions restricted to a single expression. They are expressions, so you can embed them where a def would be awkward—sort keys, map, short callbacks. For sorting, closures, and readability trade-offs, use the full Python lambda function tutorial instead of duplicating long examples here.
square = lambda x: x * x
print(square(5))That prints 25. Prefer a named def whenever the logic spans multiple statements or needs a docstring.
Built-in vs user-defined functions
Built-in functions (len, print, sorted, …) ship with the interpreter and are always available; the built-in functions index lists them. User-defined functions are the ones you write with def (or lambda). Built-ins cover common primitives; you define functions for your domain rules. In day-to-day code you mostly rely on built-ins plus libraries for generic tools, and use def (and short lambda expressions when appropriate) for program-specific behavior. Generators (yield) and async def coroutines are specialized forms—learn them after plain functions feel natural.
Common mistakes with Python functions
- Calling
greetinstead ofgreet()runs nothing and shows<function greet at ...>only if you print the object—beginners often forget the parentheses. - Missing colon after the header causes an immediate
SyntaxError. - Inconsistent indentation under
defraisesIndentationErroror changes which lines belong to the function. - Returning a value but ignoring it at the call site loses the result—capture it in a variable or use it in an expression.
- Printing for debugging inside a function when callers need a computed value—use
returnso other code can reuse the result. - Mutable defaults such as
def append_bad(x, items=[])reuse one list; useitems=Noneand setitems = []inside the body when needed. - Passing positional arguments in the wrong order for order-sensitive APIs—use keyword arguments or clearer parameter names.
- Treating “parameter” and “argument” as identical in your head—mix-ups show up when reading tracebacks and stack traces.
- Assuming a missing
returnyieldsFalseor0; it yieldsNone.
Python function quick reference table
| Topic | What to write | Remember |
|---|---|---|
| Define | def name(...): |
Colon + indented body |
| Call | name(...) |
Parentheses trigger execution |
| Return | return expr |
Omit → caller gets None |
| Defaults | def f(a, b=1) |
Defaults bind once at definition |
| Keywords | f(divisor=2, dividend=8) |
Pairs name to parameter |
| Var positional | def f(*args) |
Tuple of extras |
| Var keyword | def f(**kwargs) |
Dict of extras |
| Docstring | First string in body | Used by help() |
Summary
Python functions start with def, take optional parameters, run an indented body, and optionally return values—including tuples built with commas. Defaults and keyword arguments make APIs flexible; *args and **kwargs forward arbitrary positional and keyword bundles. Watch mutable defaults, None returns, and the difference between referencing a function and calling it. When you need more depth than this overview, use the lambda and multiple-return sections above—they link to focused follow-up guides.
References
- Defining functions in the Python tutorial
- More on defining functions (defaults, keywords,
*name,**name) - The
returnstatement - Built-in functions

