Dans la série « Ce qui me fait préférer Python » : « arguments optionnels et nommés »

Une des fonctionnalités qui me fait préférer Python à d'autre langage est la possibilité d'utiliser des arguments nommés dans les fonctions ou les méthodes.

Exemple en PHP

Je commence par écrire une fonction avec des paramètres optionnels :

<?php

function affiche_contact($nom, $prenom, $telephone1 = "", $telephone2 = "", $email = "")
{
    print("Nom : $nom\n");
    print("Prénom : $prenom\n");
    print("Téléphone1 : $telephone1\n");
    print("Téléphone2 : $telephone2\n");
    print("Email : $email);
}

?>

J'affiche un contact sans spécifier aucun argument optionnel :

<?php
affiche_contact("Dupond", "Pierre");
?>

Jusque là tout va bien. A noter tout de même que sans lire l'entête de la fonction, il n'est pas possible de savoir à quoi correspond chaque argument. De plus il n'est pas possible d'envoyer en premier argument le prénom puis le nom. L'entête de la fonction déclare que c'est d'abord le nom, puis le prénom, il n'est pas possible de changer cet ordre lors de l'appel de la fonction. Vous comprendrez ensuite pourquoi j'ai donné cette précision.

J'affiche un contact mais cette fois je spécifie l'argument optionnel $telephone1 :

<?php
affiche_contact("Dupond", "Pierre", "03 87 20 25 20");
?>

Toujours aucun problème, l'argument $telephone1 est le premier argument optionnel.

Je souhaite maintenant afficher un contact avec un numéro de téléphone et une adresse mail :

<?php
affiche_contact("Dupond", "Pierre", "03 87 20 25 20", "", "dupond.pierre@example.com");
?>

Comme vous pouvez le voir, si je souhaite passer le paramètre $email je suis obligé d'envoyer l'argument $telephone2. Ceci n'est vraiment pas pratique ni élégant. De plus, je dois avoir connaissance de la valeur par défaut du paramètre que je ne souhaitais pas envoyer.

Ce cas de figure est une vrai limite au arguments optionnels des fonctions du langage PHP. J'ai souvent été confronté à ce problème qui est vraiment énervant lorsque l'on souhaite étendre les fonctionnalités d'une fonction sans casser une API existante.

Exemple en Python

Je commence par écrire une fonction avec des paramètres optionnels :

def affiche_contact(nom, prenom, telephone1 = "", telephone2 = "", email = ""):
    print ("""Nom : %s
        Prénom : %s
        Téléphone1 : %s
        Téléphone2 : %s
        Email : %s""" % (nom, prenom, telephone1, telephone2, email))

J'affiche un contact sans spécifier aucun arguement optionnel tout comme avec la syntax PHP :

affiche_contact("Dupond", "Pierre")

Je peux aussi utiliser la syntaxe suivante :

affiche_contact(nom = "Dupond", prenom = "Pierre")

Cette syntaxe nous indique la correspondance de chaque champ envoyé. Cela évite au lecteur de consulter l'entête de la fonction.

Je peux aussi envoyer les aguments dans un ordre quelconque :

affiche_contact(prenom = "Pierre", nom = "Dupond")

J'affiche un contact mais cette fois je spécifie l'arguement optionnel telephone1 :

affiche_contact("Dupond", "Pierre", "03 87 20 25 20")

L'argument telephone1 est le premier arguement optionnel, il n'est donc pas obligatoire de le nommer.

Je souhaite maintenant afficher un contact avec un numéro de téléphone et une adresse mail :

affiche_contact("Dupond", "Pierre", "03 87 20 25 20", email = "dupond.pierre@example.com")

Comme vous pouvez le constater, j'ai envoyé uniquement les paramètres optionnels que je souhaite transmettre, contrairement à PHP je n'ai pas besoin de transmettre le paramètre telephone2.

Les arguments optionnels nommés sont vraiment une fonctionnalité Python très pratique. Cela permet de vraiment choisir les paramètres que l'on souhaite envoyer sans se soucier de l'ordre de ces derniers.

Les arguments nommés ont aussi l'avantage d'indiquer au lecteur le nom de l'argument envoyé sans avoir à regarder l'entête de la fonction.

Solution de contournement en PHP

En PHP, il y a aussi une méthode pour produire plus ou moins le même effet.

Exemple :

<?php

function affiche_contact($data)
{
    if (!isset($data['telephone1'])) $data['telephone1'] = '';
    if (!isset($data['telephone2'])) $data['telephone2'] = '';
    if (!isset($data['email'])) $data['email'] = '';

    print("Nom : " . $data['nom'] . "\n");
    print("Prénom : " . $data['prenom'] . "\n");
    print("Téléphone1 :" . $data['telephone1'] . "\n");
    print("Téléphone2 :" . $data['telephone2'] . "\n");
    print("Email :" . $data['email']);
}

?>

Puis lors de l'appel de la fonction :

<?php

affiche_contact(array("nom": "Dupond", "prenom": "Pierre"));
affiche_contact(array("nom": "Dupond", "prenom": "Pierre", "telephone1": "03 87 20 25 20"));
affiche_contact(array(
    "nom" => "Dupond",
    "prenom" => "Pierre",
    "telephone1" => "03 87 20 25 20",
    "email" => "dupond.pierre@example.com"
));

?>

Ceci est plus long (surtout dans le corps de la fonction) et moins élégant qu'en Python où cette fonctionnalité est directement intégrée au langage.

Conclusion

Je trouve que cette fonctionnalité du langage Python est très pratique bien qu'elle ne soit pas une killer feature du langage.

Références

Pour finir, quelques références :

blog comments powered by Disqus

Mes flux :