Skip to main content

How to Invoke Functions with and without Parentheses in Python

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}!"

# Calling the function: executes immediately
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!"

# No parentheses: stores the function reference, NOT the return value
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!"

# No parentheses: stores the function reference, NOT the return value
func_ref = greet

# Call the function through its reference
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
Watch for this in conditionals

This mistake is especially subtle in if statements:

def is_valid():
return False

# BUG: Function reference is always truthy, so this is always True!
if is_valid:
print("Valid") # This always prints!

# CORRECT: Call the function to get the actual boolean result
if is_valid():
print("Valid") # This correctly checks the return value

A function object is always truthy in Python, so if is_valid: (without parentheses) will always evaluate to True, regardless of what the function returns.

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]

# Pass the function reference: map() calls it on each element
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:

# WRONG: This calls square() immediately with no argument
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]

# Pass function reference: filter() calls it on each element
evens = list(filter(is_even, numbers))
print(evens)

Output:

[2, 4, 6]

Using with sorted() and key

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

# Pass the len function reference as the sorting key
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

# Create a shorter alias
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

# Store function references in a dictionary
operations = {
"+": add,
"-": subtract,
"*": multiply,
}

# Call the appropriate function based on user input
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:
# Simulate successful data fetch
data = {"status": "ok", "url": url}
success_callback(data) # Call the callback when done
except Exception as e:
failure_callback(str(e))

# Pass function references as callbacks
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!"

# WITH parentheses: calls the function, gets the return value
result_with = greet()
print(f"With parentheses: {result_with}")
print(f"Type: {type(result_with)}")

print()

# WITHOUT parentheses: gets the function object itself
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

SyntaxWhat HappensResult
func()Executes the function immediatelyThe function's return value
funcReferences the function objectThe function object itself
var = func()Stores the return valuevar holds whatever func returns
var = funcStores the function referencevar becomes callable, same as func
map(func, data)Passes function reference to mapmap 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.