2.15. Arguments

Une fonction peut être appelée de plusieurs manières, et ses paramètres peuvent être déclarés sous plusieurs formes. Les combinaisons paraissent intimidantes au premier abord ; trois ou quatre motifs couvrent presque tout en pratique.

2.15.1. Arguments positionnels et nommés

L’appel le plus simple passe les arguments par position – la première valeur va au premier paramètre, la deuxième au deuxième, et ainsi de suite :

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

rect(10, 20, 100, 50)

Le même appel peut passer les arguments par mot-clé, en nommant chaque paramètre explicitement :

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

Les arguments nommés sont indépendants de l’ordre et rendent les appels auto-documentés, au prix d’un peu plus de frappe. Les arguments positionnels et nommés peuvent se mélanger dans un même appel, mais chaque positionnel doit apparaître avant tout argument nommé :

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

2.15.2. Valeurs par défaut

Un paramètre peut déclarer une valeur par défaut à utiliser lorsque l’appelant n’en fournit pas :

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

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

Les paramètres avec valeurs par défaut doivent venir après les paramètres sans valeur par défaut dans la ligne def.

Avertissement

Les valeurs par défaut sont évaluées une seule fois, lors de l’exécution du def – et non à chaque appel. Utiliser une valeur par défaut mutable ([], {}) fait que le même objet est partagé par tous les appels qui prennent la valeur par défaut. Utilisez plutôt None comme sentinelle :

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

2.15.3. Longueur variable : *args et **kwargs

Un paramètre préfixé par * collecte tous les arguments positionnels restants dans un tuple. Un paramètre préfixé par ** collecte tous les arguments nommés restants dans un dict. Les noms conventionnels sont args et kwargs, mais n’importe quel identifiant fonctionne :

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

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

Sortie

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

Une fonction a rarement besoin des deux. L’usage le plus courant est de transmettre des arguments d’un wrapper vers un appel interne :

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

La syntaxe symétrique au site d’appel déballe un itérable en arguments positionnels (*) ou un dict en arguments nommés (**) :

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. Paramètres nommés uniquement

Un * seul dans la liste des paramètres (non rattaché à un nom) marque tous les paramètres qui le suivent comme nommés uniquement – l’appelant doit utiliser le nom :

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

Utilisez ceci pour les drapeaux booléens et autres arguments dont une valeur nue au site d’appel ne serait pas explicite.