def add_item(item, basket=[]): # DANGER: default list is created ONCE at def time basket.append(item) return basketadd_item("apple") # ['apple']add_item("banana") # ['apple', 'banana'] -- the SAME list persists across calls!
Fix by using None as the sentinel default:
def add_item(item, basket=None): if basket is None: basket = [] basket.append(item) return basket
def describe(name, age): return f"{name} is {age}"describe("Bob", 25) # positionaldescribe(name="Bob", age=25) # keyworddescribe(age=25, name="Bob") # keyword args can be reordereddescribe("Bob", age=25) # mixed, positional must come first
Enforcing Argument Style: / and *
def func(a, b, /, c, d, *, e, f): # a, b: positional-only (cannot be passed as keywords) # c, d: positional or keyword # e, f: keyword-only (must be passed as keywords) passfunc(1, 2, 3, 4, e=5, f=6) # validfunc(a=1, b=2, c=3, d=4, e=5, f=6) # TypeError, a and b are positional-onlyfunc(1, 2, 3, 4, 5, 6) # TypeError, e and f must be keyword
Why use * for keyword-only args
Forcing keyword-only arguments (common in library APIs) makes call sites self-documenting: create_user("bob", is_admin=True) is far clearer than create_user("bob", True).
Return Values
def divide(a, b): if b == 0: return None # explicit early return return a / bdef min_max(nums): return min(nums), max(nums) # returns a tuple, "multiple return values"low, high = min_max([3, 1, 4])
Docstrings
def add(a, b): """ Add two numbers together. Args: a (int or float): first number b (int or float): second number Returns: int or float: the sum of a and b """ return a + bprint(add.__doc__) # prints the docstringhelp(add) # nicer formatted output in interactive shells
Function Annotations (Type Hints on Functions)
def add(a: int, b: int) -> int: return a + b
Annotations are not enforced at runtime by default, they are documentation and static-analysis hints. See Type-Hints-and-Typing for the full system.
Functions Are First-Class Objects
Functions can be assigned to variables, passed as arguments, returned from other functions, and stored in data structures.