Python Functions: Arguments, *args, **kwargs and Lambdas

Part 6 of the Python for Everyone track. Last updated: September 2026.

Functions are where Python's flexibility shows: default arguments, keyword arguments, *args/**kwargs, and lambdas. Understand these and you can read virtually any Python library's API.

Defining and calling

def greet(name, greeting="Hello"):
    """Return a greeting string. (This is a docstring — always write one.)"""
    return f"{greeting}, {name}!"

print(greet("Ada"))                    # Hello, Ada!  (default used)
print(greet("Ada", "Hi"))              # Hi, Ada!
print(greet(name="Grace", greeting="Yo"))  # keyword args — order doesn't matter

A function without return returns None. A function can return multiple values — they're packed into a tuple:

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

lo, hi, avg = stats([4, 8, 15, 16, 23, 42])  # unpack on receipt

*args and **kwargs

def log(*args, **kwargs):
    print("positional:", args)   # args arrives as a TUPLE
    print("keyword:", kwargs)    # kwargs arrives as a DICT

log(1, 2, 3, user="ada", level="info")
# positional: (1, 2, 3)
# keyword: {'user': 'ada', 'level': 'info'}

# Unpacking at the CALL site (the reverse operation)
nums = [3, 1, 2]
print(*nums)              # same as print(3, 1, 2)
config = {"sep": "-", "end": "!\n"}
print("a", "b", **config) # same as print("a", "b", sep="-", end="!\n")

This is the #1 interview question on functions: "What do *args and **kwargs do?" — now you know.

Lambdas: tiny anonymous functions

double = lambda x: x * 2
print(double(5))  # 10

# Where they actually get used: sorting and callbacks
users = [("Ada", 36), ("Grace", 85), ("Alan", 41)]
users.sort(key=lambda u: u[1])   # sort by age
print(users)  # [('Ada', 36), ('Alan', 41), ('Grace', 85)]

Rule: if the lambda needs more than one expression, write a real def instead.

Scope: the LEGB rule

x = "global"

def f():
    x = "enclosing?"
    def g():
        # x = "local"   # uncommenting this would shadow, not change, outer x
        print(x)        # prints "enclosing?" — LEGB: Local, Enclosing, Global, Built-in
    g()

f()

Assigning inside a function creates a local variable. To modify a global, declare global x first — but needing it is usually a design smell.

The mutable-default-argument trap

# WRONG — the list is created once and shared across calls!
def add(item, bag=[]):
    bag.append(item)
    return bag

# RIGHT — use None as the default
def add(item, bag=None):
    if bag is None:
        bag = []
    bag.append(item)
    return bag

This is a classic interview gotcha. Defaults are evaluated once at function definition time.

Key takeaways

  • *args collects positional args into a tuple; **kwargs collects keyword args into a dict.
  • Multiple return values come back as a tuple — unpack them.
  • Lambdas for one-expression throwaways (especially sort(key=...)).
  • Never use a mutable object as a default argument.

Next in this series: Python OOP Part 1: Classes and Objects.

Comments

Popular posts from this blog

Java Banking Finance Services and Insurance (BFSI) domain interview questions

JSP Servlet Interview Questions For Freshers Series 1

Java program to check even or odd number