AlgoInsight

Q&A

How to declare a function in Python

By AlgoInsight Team2026-06-18awspython

Overview

Functions are the primary building block for reusable code in Python. def defines them; Python is flexible with how you pass arguments, making function signatures expressive. Because functions are objects, they're also the foundation for decorators, higher-order programming, and callbacks.

graph TD
    A["def name(params):"] --> B[Positional params]
    A --> C["Default params: x=10"]
    A --> D["*args: variadic positional"]
    A --> E["**kwargs: variadic keyword"]
    A --> F[return value or None]
    style A fill:#1e1b4b,color:#fff

Basic Function

def greet(name):
    """Return a greeting string."""    # docstring (optional but good practice)
    return f"Hello, {name}!"

print(greet("Ada"))   # Hello, Ada!

A function without return returns None implicitly.

Default Parameter Values

def power(base, exp=2):
    return base ** exp

power(3)        # 9  (exp defaults to 2)
power(3, 3)     # 27

Default values are evaluated once at definition time - a famous gotcha with mutable defaults:

# BAD: list is shared across all calls
def bad_append(x, lst=[]):
    lst.append(x)
    return lst

# GOOD: use None as sentinel
def good_append(x, lst=None):
    if lst is None:
        lst = []
    lst.append(x)
    return lst

Positional vs Keyword Arguments

At call time, arguments can be positional (by order) or keyword (by name):

def move(x, y, speed=1):
    ...

move(10, 20)              # positional
move(x=10, y=20)          # keyword
move(10, y=20, speed=3)   # mixed (positional must come first)

*args - Variable Positional Arguments

def add(*numbers):
    return sum(numbers)

add(1, 2, 3, 4)   # 10

*args collects extra positional arguments into a tuple.

**kwargs - Variable Keyword Arguments

def describe(**attrs):
    for k, v in attrs.items():
        print(f"{k}: {v}")

describe(name="Ada", role="engineer")

**kwargs collects extra keyword arguments into a dict.

Keyword-Only Parameters (after *)

def connect(host, *, port=80, timeout=30):
    ...
    
connect("example.com")            # port/timeout use defaults
connect("example.com", port=443)  # keyword only - can't pass port positionally

Parameters after a bare * can only be passed by name.

Positional-Only Parameters (before /, Python 3.8+)

def circle_area(r, /):
    return 3.14159 * r * r

circle_area(5)            # works
circle_area(r=5)          # ❌ TypeError - positional-only

Return Values

A function can return any object, or nothing (None), or multiple values via a tuple:

def minmax(lst):
    return min(lst), max(lst)    # returns a tuple

lo, hi = minmax([3, 1, 4, 1, 5])    # tuple unpacking

Lambda - Anonymous One-Expression Function

double = lambda x: x * 2
sorted(items, key=lambda item: item["price"])

lambda is limited to a single expression; use def for anything more complex.

Functions Are First-Class

def apply(func, value):
    return func(value)

apply(str.upper, "hello")   # "HELLO"
apply(lambda x: x * 3, 4)  # 12

Nested Functions and Closures

def outer(x):
    def inner(y):
        return x + y      # inner captures x from the enclosing scope
    return inner

add5 = outer(5)
add5(3)    # 8

Why This Matters in Interviews

Python interviews use function declaration to test argument mechanics. Key points: default-mutable-argument pitfall (use None sentinel), *args/**kwargs for variadic signatures, keyword-only parameters (after *), functions as first-class objects, and closures. Understanding call-time positional vs keyword matching and the parameter ordering rules (positional / standard * keyword-only **kwargs) are common follow-ups.

Common Pitfalls

References

More answers