2.15. Argumenten

Een functie kan op verschillende manieren worden aangeroepen, en de parameters ervan kunnen in verschillende vormen worden gedeclareerd. De combinaties lijken in eerste instantie intimiderend; in de praktijk dekken drie of vier patronen vrijwel alles.

2.15.1. Positionele en keyword-argumenten

De eenvoudigste aanroep geeft argumenten door op positie – de eerste waarde gaat naar de eerste parameter, de tweede naar de tweede, enzovoort:

def rect(x, y, w, h):
    return (x, y, w, h)

rect(10, 20, 100, 50)

Dezelfde aanroep kan argumenten doorgeven via keyword, waarbij elke parameter expliciet wordt benoemd:

rect(x=10, y=20, w=100, h=50)

Keyword-argumenten zijn volgorde-onafhankelijk en maken aanroepen zelfdocumenterend, tegen de prijs van meer typewerk. Positionele en keyword-argumenten kunnen in één aanroep worden gecombineerd, maar elke positionele moet vóór elke keyword komen:

rect(10, 20, w=100, h=50)         # OK
rect(x=10, 20, 100, 50)           # SyntaxError

2.15.2. Standaardwaarden

Een parameter kan een standaardwaarde declareren die wordt gebruikt wanneer de aanroeper er geen opgeeft:

def greet(name, greeting="hello"):
    print(greeting, name)

greet("Alice")                    # hello Alice
greet("Alice", "hi")              # hi Alice
greet("Alice", greeting="hey")    # hey Alice

Parameters met standaardwaarden moeten na parameters zonder standaardwaarden komen in de def-regel.

Waarschuwing

Standaardwaarden worden eenmalig geëvalueerd, wanneer de def wordt uitgevoerd – niet bij elke aanroep. Het gebruik van een veranderbare standaardwaarde ([], {}) zorgt ervoor dat hetzelfde object wordt gedeeld over elke aanroep die de standaardwaarde gebruikt. Gebruik in plaats daarvan None als sentinel:

def append_to(item, target=None):
    if target is None:
        target = []
    target.append(item)
    return target

2.15.3. Variabele lengte: *args en **kwargs

Een parameter met het voorvoegsel * verzamelt alle overgebleven positionele argumenten in een tuple. Een parameter met het voorvoegsel ** verzamelt alle overgebleven keyword-argumenten in een dict. De conventionele namen zijn args en kwargs, maar elke identifier werkt:

def report(label, *values, **options):
    print(label, values, options)

report("temps", 21, 22, 23, unit="C", precision=1)

Uitvoer:

temps (21, 22, 23) {'unit': 'C', 'precision': 1}

Een functie heeft zelden beide nodig. Het meest voorkomende gebruik is het doorgeven van argumenten van een wrapper naar een interne aanroep:

def log_and_call(func, *args, **kwargs):
    print("calling", func.__name__)
    return func(*args, **kwargs)

De spiegelbeeldsyntaxis op de aanroep-plek pakt een iterable uit in positionele argumenten (*) of een dict in keyword-argumenten (**):

point = (10, 20, 100, 50)
rect(*point)                      # same as rect(10, 20, 100, 50)

kwargs = {"x": 10, "y": 20, "w": 100, "h": 50}
rect(**kwargs)                    # same as rect(x=10, y=20, ...)

2.15.4. Keyword-only parameters

Een * op zichzelf in de parameterlijst (niet verbonden aan een naam) markeert elke daaropvolgende parameter als keyword-only – de aanroeper moet de naam gebruiken:

def crop(buffer, *, x, y, w, h):
    ...

crop(buffer, x=0, y=0, w=100, h=100)   # OK
crop(buffer, 0, 0, 100, 100)           # TypeError

Gebruik dit voor booleaanse vlaggen en andere argumenten waarbij een kale waarde op de aanroep-plek niet vanzelfsprekend zou zijn.