Functions as Variables in Python 2026

Writing Functions Mar 16, 2026

Functions as Variables in Python 2026

In Python, functions are first-class citizens. This means you can assign functions to variables, pass them as arguments, return them from other functions, and store them in data structures. Treating functions as variables unlocks powerful and elegant programming patterns.

TL;DR — Key Takeaways 2026

  • Functions can be assigned to variables just like any other object
  • This enables dynamic behavior, callbacks, and strategy patterns
  • Use function variables to create cleaner and more flexible code
  • Combine with type hints for better clarity and IDE support

1. Basic Assignment


def greet(name: str) -> str:
    return f"Hello, {name}!"

# Assign function to a variable
say_hello = greet

print(say_hello("Alice"))        # Hello, Alice!
print(greet("Bob"))              # Hello, Bob!

2. Real-World Patterns


# 1. Strategy Pattern
def format_json(data):
    return {"status": "success", "data": data}

def format_xml(data):
    return f"<result><status>success</status><data>{data}</data></result>"

def process_request(data, formatter):
    return formatter(data)

# Choose formatter dynamically
response = process_request({"user": "Alice"}, format_json)

# 2. Callback pattern
def on_success(result):
    print(f"Operation succeeded: {result}")

def on_error(error):
    print(f"Operation failed: {error}")

def perform_operation(callback_success, callback_error):
    try:
        result = do_something()
        callback_success(result)
    except Exception as e:
        callback_error(e)

3. Best Practices in 2026

  • Use descriptive variable names when assigning functions
  • Combine with type hints for better readability and IDE support
  • Use function variables for dynamic behavior and strategy patterns
  • Store functions in dictionaries for clean dispatch logic
  • Avoid deep nesting of function assignments for maintainability

Assigning a Function to a Variable

Writing alias = some_function creates a second name for the same function object. No copy is made and nothing is called. Both names can now be used to call it, and alias.__name__ still reports the original name.

This is useful for choosing behaviour at runtime. A script can pick a function based on a setting, store it in one variable and call that variable later, without if statements spread through the code.

Rebinding the original name afterwards does not affect the alias, because the alias points to the old function object. This is the same rule as for any other value in Python.

Assigning functions is also how you swap in a fake function during testing, although unittest.mock offers safer tools for that.

Worked Example: Choosing a Formatter at Runtime

We choose one of two formatting functions from a setting and use the chosen one through a variable.

def as_percent(x: float) -> str:
    return f"{x:.1%}"

def as_ratio(x: float) -> str:
    return f"{x:.3f}"

style = "percent"
fmt = as_percent if style == "percent" else as_ratio

for value in [0.1234, 0.5]:
    print(fmt(value))

print(fmt is as_percent, fmt.__name__)

def as_percent(x: float) -> str:      # redefine the original name
    return "changed"
print(fmt(0.25))

The variable fmt refers to as_percent, so it prints 12.3% and 50.0%, and the identity check is True. After the name as_percent is redefined, fmt still holds the old function object and prints 25.0%.

Practical Tips

Choose the function once, near the start of the program or in a configuration step, and pass the chosen function to the code that needs it. This keeps the decision in one place and makes the rest of the code simpler.

When the choice depends on a string setting, a dictionary from setting names to functions is clearer than a chain of if statements. It also lets you list the valid options for an error message.

Use descriptive alias names, such as formatter or loader, so the role is clear even when the chosen function changes.

Remember that classes and methods can be assigned to variables in the same way, because they are objects too.

A short print of fmt.__name__ in logs shows which function was chosen at runtime.

Common Mistakes

  • Adding parentheses and storing a result instead of the function.
  • Expecting an alias to follow later redefinitions.
  • Using many if statements where one chosen function would do.
  • Giving aliases names that hide what the function does.

Quick Summary

  • Assignment creates another name, not a copy.
  • Choose behaviour once, call it many times.
  • Aliases keep the original object.
  • __name__ shows the original name.

Conclusion

Treating functions as variables is one of Python’s most powerful features. In 2026, using this capability effectively allows you to write more flexible, modular, and elegant code. From simple callbacks to complex strategy patterns, functions as variables unlock many design possibilities.

Next steps:

  • Look for opportunities in your code to use functions as variables instead of hardcoded behavior

Related Tutorials

Share:
Last updated: March 2026
Built-in Functions in Python 2026 str() in Python 2026: String Conversion + Modern Formatting & Best Practices memoryview with JAX in Python 2026: Zero-Copy NumPy → JAX Array Interop + Efficient ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + GPU Pinning & ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + ML Examples memoryview with NumPy & PyTorch in Python 2026: Zero-Copy Views, Efficient Slicing & ML Interop Examples memoryview with NumPy in Python 2026: Zero-Copy Views, Efficient Slicing & Real ML Examples memoryview() in Python 2026: Zero-Copy Magic for Large Binary Data + Real Examples import() in Python 2026: How It Works, Security Risks & Modern Alternatives (importlib) zip() in Python 2026: How to Use It, strict=True Behavior & Real-World Examples vars() in Python 2026: Accessing Object Namespace + Modern Introspection Patterns type() in Python 2026: Dynamic Type Inspection & Object Creation + Modern Patterns tuple() in Python 2026: Immutable Sequences + Modern Patterns & Best Practices super() in Python 2026: Method Resolution & Modern Inheritance Patterns sum() in Python 2026: Summing Iterables + Modern Numeric Patterns & Best Practices staticmethod() in Python 2026: Static Methods, Utility Functions & Modern Best Practices sorted() in Python 2026: Sorting Iterables + Modern Patterns & Best Practices slice() in Python 2026: Creating Slice Objects + Modern Patterns & Best Practices setattr() in Python 2026: Dynamic Attribute Setting + Modern Patterns & Safety set() in Python 2026: Mutable Sets Creation + Modern Patterns & Best Practices