Skip to content

How to Invoke Functions with and without Parentheses in Python

Learn how Python executes functions with parentheses and treats them as references without them, including key differences for callbacks, decorators, and higher-order functions.

One of the most important distinctions in Python is the difference between calling a function and referencing a function. Adding parentheses () after a function name executes it immediately, while omitting them treats the function as an object: a reference that can be stored, passed around, or called later.

Understanding this distinction is essential for working with callbacks, higher-order functions, decorators, event handlers, and many other Python patterns.

In this guide, you'll learn when and why to use each approach, with practical examples and common pitfalls to avoid.

Invoking a Function with Parentheses

When you write a function name followed by parentheses (), Python executes the function immediately and returns its result:

def greet(name="World"):
    return f"Hello, {name}!"

result1 = greet()
result2 = greet("Tom")

print(result1)
print(result2)

Output:

Hello, World!
Hello, Tom!

Key points:

  • greet() calls the function with no arguments, so the default parameter "World" is used.
  • greet("Tom") calls the function with "Tom" as the argument.
  • In both cases, the function executes and the return value is stored in the variable.

Referencing a Function without Parentheses

When you write a function name without parentheses, Python does not execute it. Instead, it returns a reference to the function object itself:

def greet():
    return "Hello!"

func_ref = greet

print(func_ref)
print(type(func_ref))

Output:

<function greet at 0x7d123fc98180>
<class 'function'>

The variable func_ref now holds the function object. You can call it later by adding parentheses:

def greet():
    return "Hello!"

func_ref = greet

result = func_ref()
print(result)

Output:

Hello!

Common Mistake: Forgetting Parentheses When You Want to Call

A frequent bug is assigning a function reference when you actually intended to call the function:

Wrong approach: missing parentheses

def get_status():
    return "Active"

status = get_status  # Missing parentheses!
print(status)

Output:

<function get_status at 0x7f9a2c103100>

Instead of the string "Active", you get the function object. This often leads to confusing bugs downstream.

Correct approach: include parentheses to call the function

def get_status():
    return "Active"

status = get_status()  # Parentheses execute the function
print(status)

Output:

Active

When to Use Functions without Parentheses

Omitting parentheses is intentional and necessary in several important Python patterns.

Passing Functions to Higher-Order Functions

Higher-order functions like map(), filter(), and sorted() accept other functions as arguments. You pass the function by reference (without parentheses), and the higher-order function calls it internally:

def square(n):
    return n * n

numbers = [1, 2, 3, 4, 5]

squared = list(map(square, numbers))
print(squared)

Output:

[1, 4, 9, 16, 25]

If you accidentally added parentheses, you'd call square immediately (with no argument), causing an error:

squared = list(map(square(), numbers))

Output:

TypeError: square() missing 1 required positional argument: 'n'

Using with filter()

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

numbers = [1, 2, 3, 4, 5, 6]

evens = list(filter(is_even, numbers))
print(evens)

Output:

[2, 4, 6]

Using with sorted() and key

words = ["banana", "apple", "cherry", "date"]

sorted_words = sorted(words, key=len)
print(sorted_words)

Output:

['date', 'apple', 'banana', 'cherry']

Assigning Functions to Variables (Aliasing)

You can create an alias for a function by assigning its reference to a new variable:

def calculate_area(radius):
    return 3.14159 * radius ** 2

area = calculate_area

print(area(5))
print(area(10))

Output:

78.53975
314.159

Storing Functions in Data Structures

Functions can be stored in lists, dictionaries, or other collections for dynamic dispatch:

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

def subtract(a, b):
    return a - b

def multiply(a, b):
    return a * b

operations = {
    "+": add,
    "-": subtract,
    "*": multiply,
}

operator = "+"
result = operations[operator](10, 3)
print(f"10 {operator} 3 = {result}")

Output:

10 + 3 = 13

Callbacks and Event Handlers

Callbacks are functions passed as arguments to be called later when an event occurs:

def on_success(data):
    print(f"Success! Received: {data}")

def on_failure(error):
    print(f"Error: {error}")

def fetch_data(url, success_callback, failure_callback):
    """Simulate fetching data with callback functions."""
    try:
        data = {"status": "ok", "url": url}
        success_callback(data)  # Call the callback when done
    except Exception as e:
        failure_callback(str(e))

fetch_data("https://api.example.com", on_success, on_failure)

Output:

Success! Received: {'status': 'ok', 'url': 'https://api.example.com'}

Decorators

Decorators are a classic example of passing functions without parentheses. A decorator receives a function reference and returns a modified version:

def log_call(func):
    """Decorator that logs when a function is called."""
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__}...")
        result = func(*args, **kwargs)
        print(f"{func.__name__} returned {result}")
        return result
    return wrapper

@log_call  # Passes 'add' to log_call without parentheses
def add(a, b):
    return a + b

add(3, 5)

Output:

Calling add...
add returned 8

Side-by-Side Comparison

Here's a clear comparison showing the difference in behavior:

def greet():
    return "Hello!"

result_with = greet()
print(f"With parentheses:    {result_with}")
print(f"Type:                {type(result_with)}")

print()

result_without = greet
print(f"Without parentheses: {result_without}")
print(f"Type:                {type(result_without)}")
print(f"Callable?            {callable(result_without)}")
print(f"Called later:        {result_without()}")

Output:

With parentheses:    Hello!
Type:                <class 'str'>

Without parentheses: <function greet at 0x7a8f70ed8180>
Type:                <class 'function'>
Callable?            True
Called later:        Hello!

Quick Reference

Syntax What Happens Result
func() Executes the function immediately The function's return value
func References the function object The function object itself
var = func() Stores the return value var holds whatever func returns
var = func Stores the function reference var becomes callable, same as func
map(func, data) Passes function reference to map map calls func on each element
map(func(), data) Calls func immediately (usually a bug) Likely causes a TypeError

Conclusion

The distinction between calling a function (func()) and referencing it (func) is fundamental in Python:

  • With parentheses (): The function executes immediately and you get its return value.
  • Without parentheses: You get a reference to the function object, which can be stored, passed, or called later.

Understanding this difference is essential for:

  • Higher-order functions like map(), filter(), and sorted() where you pass function references.
  • Callbacks and event handlers where functions are executed later.
  • Decorators that receive and wrap function references.
  • Dynamic dispatch using dictionaries of functions.

The most common bug related to this concept is forgetting parentheses in conditionals (if is_valid: instead of if is_valid():), where the function reference is always truthy regardless of the function's actual return value. Use callable() to verify whether a variable holds a function reference when debugging.

Navigation