New: 6 free SQL practice datasets with 300+ questions — try the SQL Compiler →
Python

Python Functions: Arguments, Return and Scope

Python functions explained: def, arguments, default values, return vs print and variable scope, with real code and output and common mistakes.

Upskly AI Team September 26, 2026 8 min read
Python Functions: Arguments, Return and Scope

A Python function is a named block of code you can run whenever you need it. You define it with def, give it inputs (parameters), and send a result back with return. Variables created inside a function are local: they exist only while it runs. If a function never reaches a return, it gives back None.

This guide covers defining and calling functions, arguments and default values, returning results, scope and the mistakes that trip up beginners, with real output throughout.

In this guide

The short version

  • def name(parameters): defines it. name(arguments) calls it.
  • return sends a value back. No return means None.
  • Give a parameter a default (rate=0.18) to make it optional.
  • Variables assigned inside a function are local. Read globals freely, but avoid changing them.

Defining and calling a function

The def line names the function and lists its parameters. The indented lines below are its body. Nothing runs until you call the function by name with brackets:

def greet(name):
    return "Hello, " + name + "!"

message = greet("Asha")
print(message)
print(greet("Ravi"))

Output

Hello, Asha!
Hello, Ravi!

A function lets you write logic once and reuse it. It also gives that logic a name, which makes code easier to read: greet("Asha") says what it does.

Parameters, arguments and defaults

A parameter is the name in the definition (name). An argument is the actual value you pass when you call it ("Asha"). People mix the two words up constantly, and it rarely matters.

Give a parameter a default value and callers can leave it out. You can also pass arguments by name (keyword arguments), in any order:

def price_with_tax(amount, rate=0.18, currency="INR"):
    return f"{amount * (1 + rate):.2f} {currency}"

print(price_with_tax(100))
print(price_with_tax(100, 0.05))
print(price_with_tax(100, currency="USD"))
print(price_with_tax(currency="EUR", amount=200, rate=0))

Output

118.00 INR
105.00 INR
118.00 USD
200.00 EUR

Two habits pay off. Put parameters with defaults after the ones without. And use keyword arguments when a call has several values of the same type, because price_with_tax(100, 0.05) is harder to read than price_with_tax(100, rate=0.05). To accept any number of arguments, see Python *args and **kwargs Explained.

Returning values

The most common function mistake is confusing print with return. print only shows something on screen. return hands a value back so the rest of your program can use it:

def add_print(a, b):
    print(a + b)

def add_return(a, b):
    return a + b

x = add_print(2, 3)
y = add_return(2, 3)
print(x, y)

Output

5
None 5

The first function printed 5, but gave back nothing, so x is None. The second returned 5, so y holds it. If you want to use the result, return it.

Returning several values

A function can return more than one value. Python packs them into a tuple, and you can unpack them on the other side:

def stats(nums):
    return min(nums), max(nums), sum(nums) / len(nums)

low, high, avg = stats([4, 8, 6])
print(low, high, avg)
print(stats([4, 8, 6]))

Output

4 8 6.0
(4, 8, 6.0)

Scope: where variables live

A variable created inside a function is local. It is created when the function runs and disappears when it ends. Assigning to a name inside a function makes a new local variable, even if a global with the same name exists:

total = 100

def show():
    total = 5
    print("inside:", total)

show()
print("outside:", total)

Output

inside: 5
outside: 100

Outside the function, the local variable simply does not exist:

def make():
    secret = 42

make()
print(secret)

Output

NameError: name 'secret' is not defined

When Python meets a name, it looks in this order: Local (inside the function), Enclosing (an outer function), Global (the file) and Built-in (like len). It uses the first match. This is called the LEGB rule.

Changing a global from inside a function

Reading a global is fine. But assigning to it makes Python treat the name as local for the whole function, and that fails when the function reads it first:

count = 0

def add_one():
    count = count + 1

try:
    add_one()
except UnboundLocalError as e:
    print(type(e).__name__)

Output

UnboundLocalError

You can fix it with the global keyword, but that is usually a sign to redesign. Passing the value in and returning the result is cleaner and easier to test:

count = 0

def add_one():
    global count
    count += 1

add_one()
add_one()
print(count)

def add_one_better(n):
    return n + 1

print(add_one_better(count))

Output

2
3

Functions are objects too

In Python a function is a value like any other. You can store it in a variable, put it in a list, pass it to another function, or return it from one. That idea powers map(), sorted(key=...) and decorators:

def square(n):
    return n * n

operation = square
print(operation(4))
print(list(map(square, [1, 2, 3])))
print(square.__name__)

Output

16
[1, 4, 9]
square

Read on in Python Decorators Explained Step by Step and Python lambda, map, filter and reduce Explained.

Documenting a function

A string placed on the first line of the body is a docstring. Tools, editors and help() show it, so it is the natural place to say what the function does:

def area(width, height):
    """Return the area of a rectangle."""
    return width * height

print(area.__doc__)
print(area(3, 4))

Output

Return the area of a rectangle.
12

Common mistakes

Mistake 1: forgetting to return

The calculation runs, but the result is thrown away:

def double(n):
    n * 2

print(double(5))

Output

None

Mistake 2: a mutable default argument

A default value is created once, when the function is defined, not every time it is called. If it is a list or dictionary, every call shares it:

def add_item(item, basket=[]):
    basket.append(item)
    return basket

print(add_item("pen"))
print(add_item("book"))

def add_item_ok(item, basket=None):
    if basket is None:
        basket = []
    basket.append(item)
    return basket

print(add_item_ok("pen"))
print(add_item_ok("book"))

Output

['pen']
['pen', 'book']
['pen']
['book']

The first version remembered "pen" between calls. The safe pattern is to use None as the default and create the list inside the function.

Mistake 3: naming a variable after a built-in

Calling a variable list, sum, max or id hides the built-in of the same name, and the next call to it breaks:

list = [1, 2]
print(list)
try:
    list("abc")
except TypeError as e:
    print(type(e).__name__)

Output

[1, 2]
TypeError

Mistake 4: changing globals inside functions

It makes code hard to follow and test. Pass values in and return results instead.

Try it yourself

Work out each answer first, then open the solution.

1. Write is_even(n) that returns True or False.

Show solution
def is_even(n):
    return n % 2 == 0

print(is_even(4), is_even(7))

Output

True False

The comparison n % 2 == 0 is already a boolean, so you can return it directly.

2. Write average(nums) that returns the mean of a list.

Show solution
def average(nums):
    return sum(nums) / len(nums)

print(average([2, 4, 9]))

Output

5.0

3. What does this print?

x = 10

def f():
    x = 20
    return x

print(f(), x)
Show answer

Output

20 10

The x = 20 inside f creates a local variable. The global x is untouched.

4. What does this print?

def f(a, b=2):
    return a * b

print(f(3), f(3, 4), f(b=5, a=1))
Show answer

Output

6 12 5

f(3) uses the default b=2, f(3, 4) overrides it, and the keyword call f(b=5, a=1) works in any order.

Run these in our free Python compiler.

Frequently asked questions

What is the difference between a parameter and an argument?

A parameter is the variable name in the function definition. An argument is the actual value you pass in when you call the function. In greet("Asha"), "Asha" is the argument.

What is the difference between print and return?

print displays a value on screen and gives back None. return sends a value back to the caller so it can be stored or used in further calculations.

Can a Python function return multiple values?

Yes. return a, b returns a tuple, which you can unpack: x, y = func().

What does a function return if there is no return statement?

None. The function still runs, but the caller gets None back.

What is variable scope in Python?

Scope decides where a name can be used. A variable assigned inside a function is local to it. Python searches Local, then Enclosing, then Global, then Built-in scopes for a name (the LEGB rule).

When should I use the global keyword?

Rarely. It lets a function assign to a module-level variable, but it makes code harder to understand and test. Prefer passing values as arguments and returning results.

Run this code in your browser

The free Upskly compiler runs Python with nothing to install. Paste the example, change it and see what happens.

Open Python Compiler

Stuck on a traceback?

AI Assist works inside the Python notebook, so you can ask about an error or a concept without leaving the cell.

Try AI Assist

Test yourself

Timed questions on Functions, Scope and Closures, with an explanation for every answer.

Take the Quiz
Upskly AI Team
Learning made simple
Scroll to Top