Module lessons (2/4)
Default and keyword parameters
Function parameters can have default values: if the caller doesn't pass them, the defaults are used. You can also call a function passing parameters by name (keyword arguments).
Default parameters
def saluta(nome, saluto="Ciao"):
return f"{saluto}, {nome}!"
saluta("Ada") # 'Ciao, Ada!'
saluta("Ada", "Hello") # 'Hello, Ada!'Parameters with defaults must come after those without:
def f(a, b=1): # OK
def f(a=1, b): # SyntaxErrorKeyword arguments
You can pass arguments by name, in any order, making the call more readable:
def crea_utente(nome, eta, attivo=True):
return {"nome": nome, "eta": eta, "attivo": attivo}
crea_utente("Ada", 36)
crea_utente(nome="Ada", eta=36, attivo=False)
crea_utente(eta=36, nome="Ada") # any order when all are keywordGolden rule: in a call, positional arguments come BEFORE keyword arguments.
crea_utente("Ada", eta=36) # OK
crea_utente(nome="Ada", 36) # SyntaxError⚠️ The mutable default pitfall
NEVER use a mutable object (list, dict, set) as a default value: the default is evaluated ONCE, when the function is defined, and shared across all calls.
def aggiungi(elemento, lista=[]): # BUG!
lista.append(elemento)
return lista
aggiungi(1) # [1]
aggiungi(2) # [1, 2] !!! not [2] as you'd expect
aggiungi(3) # [1, 2, 3]The correct pattern: use None as a sentinel and create it inside:
def aggiungi(elemento, lista=None):
if lista is None:
lista = []
lista.append(elemento)
return listaThe danger of mutable default arguments
Never use mutable objects (like lists or dictionaries) as default values for parameters: for example def add(x, my_list=[]). The default value is evaluated only once when the function is defined, meaning subsequent calls will share the exact same mutable object! The best practice is to use None:
def add(x, my_list=None):
if my_list is None:
my_list = []
my_list.append(x)
return my_listTry it
Define `power(base, exponent=2)` that returns base ** exponent. Compute `square = power(5)` and `cube = power(5, exponent=3)`. Evaluate `(square, cube)`.
Show hint
return base ** exponent
Solution available after 3 attempts
Review exercise
Define `create_record(name, values=None)` that, when values is None, uses a fresh empty list. Append 1 to values and return the record dict {'name': name, 'values': values}. Call it twice without passing values and assign to `a` and `b`. Evaluate `(a['values'], b['values'])`.
Show hint
Use None as the default and create the list inside the function.
Solution available after 3 attempts
Additional challenge
Define a function `greet(name, message="Hello")` that returns the formatted string `"{message}, {name}!"`. Test the function by calling `greet("Bob")` as the last expression.
Show hint
Use a default parameter message="Hello" and an f-string for the returned greeting.
Solution available after 3 attempts