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
Post a Comment