71 votes

Y a-t-il une raison de ne pas toujours utiliser des arguments sous forme de mots-clés ?

Avant de me lancer dans Python, j'avais commencé par lire quelques livres sur Objective-C / Cocoa. Si je me souviens bien, la plupart des fonctions exigeaient que les arguments des mots-clés soient explicitement indiqués. Jusqu'à récemment, j'ai oublié tout cela, et j'ai simplement utilisé des arguments positionnels en Python. Mais dernièrement, j'ai rencontré quelques bugs dus à des positions incorrectes - des petites choses sournoises.

Cela m'a fait réfléchir - de manière générale, à moins qu'il n'y ait une circonstance qui exige spécifiquement des arguments autres que des mots-clés - y a-t-il une bonne raison de ne pas utiliser des arguments de mots-clés ? Est-il considéré comme un mauvais style de toujours les utiliser, même pour des fonctions simples ?

J'ai l'impression que, comme la plupart de mes programmes de 50 lignes passent régulièrement à 500 lignes ou plus, si je m'habitue à toujours utiliser des arguments sous forme de mots-clés, le code sera plus facile à lire et à maintenir au fur et à mesure de sa croissance. Y a-t-il une raison pour que ce ne soit pas le cas ?

UPDATE :

L'impression générale que j'ai est qu'il s'agit d'une préférence de style, avec de nombreux arguments valables pour dire qu'ils ne devraient généralement pas être utilisés pour des arguments très simples, mais qu'ils sont par ailleurs conformes à un bon style. Avant d'accepter, je veux juste clarifier les choses - y a-t-il des problèmes spécifiques non stylistiques qui découlent de cette méthode - par exemple, des pertes de performance significatives ?

3 votes

Un endroit où j'ai vu le conseil de toujours utiliser des arguments de mots-clés est avec __init__ . Voir fuhm.net/super-harmful . Ce n'est pas aussi général que ce que vous demandez ici, mais c'est un argument en faveur de ce que vous suggérez.

0 votes

Je dirais que vous demandez pourquoi Python va dans ce sens parce qu'il vient d'Objective-C à Python. Si vous faisiez le chemin inverse, vous demanderiez pourquoi Objective-C nous oblige à utiliser des arguments de mots-clés partout ! (Non pas qu'il s'agisse d'un choix mauvais ou irrationnel ; il s'agit simplement d'une conception différente. Cependant, l'ensemble du langage en est affecté et je vous suggère donc de ne pas essayer de copier une telle conception dans un autre langage).

68voto

Rosh Oxymoron Points 6965

Il n'y a aucune raison de ne pas utiliser les arguments des mots-clés, si ce n'est pour la clarté et la lisibilité du code. Le choix d'utiliser ou non des mots-clés devrait être basé sur le fait que le mot-clé ajoute ou non des informations supplémentaires utiles à la lecture du code.

Je suis la règle générale suivante :

  1. S'il est difficile de déduire la fonction (nom) de l'argument à partir du nom de la fonction - passez-le par mot clé (par exemple, je ne voudrais pas avoir text.splitlines(True) dans mon code).
  2. S'il est difficile de déduire l'ordre des arguments, par exemple si vous avez trop d'arguments, ou si vous avez des arguments optionnels indépendants - passez-le par mot-clé (ex. funkyplot(x, y, None, None, None, None, None, None, 'red') n'a pas l'air particulièrement agréable).
  3. Ne jamais passer les premiers arguments par mot-clé si le but de l'argument est évident. Vous voyez, sin(2*pi) est meilleur que sin(value=2*pi) il en va de même pour plot(x, y, z) .

Dans la plupart des cas, les arguments obligatoires stables seront positionnels, et les arguments facultatifs seront des mots-clés.

Il y a également une différence possible en termes de performances, car dans chaque implémentation, les arguments par mot-clé seraient légèrement plus lents, mais étant donné qu'il s'agirait généralement d'une optimisation prématurée et que les résultats ne seraient pas significatifs, je ne pense pas que cela soit crucial pour la décision.

MISE À JOUR : préoccupations non stylistiques

Les arguments de type mot-clé peuvent faire tout ce que les arguments de type positionnel peuvent faire, et si vous définissez une nouvelle API, il n'y a pas d'inconvénients techniques à part d'éventuels problèmes de performance. Cependant, vous risquez d'avoir de petits problèmes si vous combinez votre code avec des éléments existants.

Considérez ce qui suit :

  • Si vous faites en sorte que votre fonction prenne des arguments de type mot-clé, cela devient une partie de votre interface. Vous ne pouvez pas remplacer votre fonction par une autre qui a une signature similaire mais un mot-clé différent pour le même argument.
  • Vous pourriez vouloir utiliser un décorateur ou un autre utilitaire sur votre fonction qui suppose que votre fonction prend un argument positionnel. Les méthodes non liées sont un exemple d'un tel utilitaire car elles passent toujours le premier argument comme positionnel après l'avoir lu comme positionnel, donc cls.method(self=cls_instance) ne fonctionne pas même s'il y a un argument self dans la définition.

Aucun de ces éléments ne constitue un réel problème si vous concevez bien votre API et si vous documentez l'utilisation des arguments des mots-clés, en particulier si vous ne concevez pas quelque chose qui doit être interchangeable avec quelque chose qui existe déjà.

12 votes

Réponse parfaite. J'ajouterais que la méthode Python est similaire à la façon dont les options de ligne de commande des programmes sont passées : les options obligatoires doivent être peu nombreuses et positionnelles, les options facultatives doivent être passées comme une option (qui est en quelque sorte un mot-clé).

0 votes

Les arguments de mots-clés peuvent-ils vraiment entraîner une baisse significative des performances ? Je suppose que c'est un ou deux tokens supplémentaires à analyser, mais y a-t-il des raisons plus profondes que cela ?

1 votes

@Rosh : Strictement parlant, l'affirmation "Les arguments de mots-clés peuvent faire tout ce que les arguments positionnels peuvent faire" n'est pas vraie. Par exemple, le déballage de tuple ne fonctionne pas pour les arguments de type mot-clé, alors que les arguments de type positionnel ne fonctionnent pas. def f((x, y)): … est une définition valide. Bien sûr, ce n'est pas un style largement utilisé ni recommandé.

19voto

bsink Points 479

Si votre objectif est d'améliorer la lisibilité des appels de fonctions, pourquoi ne pas simplement déclarer les fonctions comme d'habitude, par ex.

def test(x, y):
    print "x:", x
    print "y:", y

Et appelez simplement les fonctions en déclarant les noms explicitement, comme ceci :

test(y=4, x=1)

Ce qui vous donne évidemment la sortie :

x: 1
y: 4

ou cet exercice serait inutile.

Cela évite que les arguments soient optionnels et qu'ils aient besoin de valeurs par défaut (à moins que vous ne le souhaitiez, auquel cas il suffit d'utiliser les arguments par mot-clé ! ) et vous donne toute la polyvalence et la lisibilité améliorée des arguments nommés qui ne sont pas limités par l'ordre.

0 votes

Réponse parfaite à la question de george. faire que les args agissent comme des kwargs. on Blog de la grue salée Il montre comment mélanger les kwargs et les args dans les appels de fonction.

0 votes

Oui ! Cela donne la plupart des avantages que le post demandait, sans tous les inconvénients que la modification de la spécification des arguments de fonction créerait.

10voto

Martin Points 3187

Eh bien, il y a quelques raisons pour lesquelles je ne le ferais pas.

Si tous vos arguments sont des arguments de type mot-clé, cela augmente le bruit dans le code et peut enlever toute clarté sur les arguments requis et ceux qui sont optionnels.

Aussi, si je dois utiliser votre code, je pourrais avoir envie de vous tuer ! !! (Je plaisante), mais devoir taper le nom de tous les paramètres à chaque fois... pas très amusant.

3 votes

J'ai vu du code Smalltalk (sur lequel Obj-C est basé). Quand il est bien fait, il se lit très naturellement. Au lieu de voir une liste de paramètres, on voit une phrase. Il faut penser différemment à la façon dont on nomme les paramètres, mais quelqu'un qui vient de l'Objective-C a probablement déjà cet état d'esprit.

0 votes

Je peux voir l'argument de Noise. Pour ce qui est de savoir s'ils étaient facultatifs ou non, pouvez-vous donner un exemple ? Comme j'y pense, il faudrait comprendre le fonctionnement de la fonction pour savoir si un argument est facultatif ou non. Le fait de nommer les arguments (s'ils sont bien nommés) n'accélérerait-il pas la compréhension dans ce cas ?

0 votes

@Joe White il est vrai que cette façon d'écrire les params se sent bien dans SmallTalk/Objective-C mais c'est parce que les langages sont conçus dans leur ensemble pour l'utiliser et les développeurs de ces langages prennent beaucoup de soin à le faire bien dans la "bonne manière". Notez, par exemple, que les paramètres ObjC sont à la fois basés sur des mots-clés et positionnels, de sorte que l'apparence de la phrase est forcée. Le problème est que la "bonne manière" en Python est différente et suivre les schémas d'Objective-C donnerait un code étrange.

8voto

Brent Newey Points 2632

Pour proposer un autre argument, je pense qu'il existe des cas où les paramètres nommés peuvent améliorer la lisibilité. Par exemple, imaginez une fonction qui crée un utilisateur dans votre système :

create_user("George", "Martin", "g.m@example.com", "payments@example.com", "1", "Radius Circle")

À partir de cette définition, on ne sait pas du tout ce que ces valeurs peuvent signifier, même si elles sont toutes requises, alors qu'avec des paramètres nommés, c'est toujours évident :

create_user(
    first_name="George",
    last_name="Martin",
    contact_email="g.m@example.com",
    billing_email="payments@example.com",
    street_number="1",
    street_name="Radius Circle")

0 votes

C'est ce que j'ai aimé dans l'apprentissage de Cocoa/Obc. - Voir une fonction pour la première fois n'était pas si mystifiant - on pouvait généralement avoir une assez bonne idée de ce qu'elle faisait, ce que je trouvais génial. Je ne suis pas assez expérimenté pour savoir si le code d'un grand projet peut être suffisamment parcimonieux pour que le poids constant des arguments typés ne soit pas un problème à long terme.

3 votes

Je pense que cela dépend de la fonction. Dans le cas de quelque chose comme def validate_email(email) Il est probablement évident, lorsque vous regardez une instance de la fonction, de savoir ce qu'elle fait.

1 votes

En effet, les arguments de type mot-clé sont vraiment utiles pour passer des littéraux à une fonction. Cependant, si les arguments sont des variables avec des noms suffisamment clairs, cela devient très bruyant. Considérez : create_user(first_name=first_name, last_name=last_name, contact_email=contact_email, ...) .

5voto

BasicWolf Points 8119

Je me souviens avoir lu une très bonne explication des "options" dans les programmes UNIX : "Les options sont censées être facultatives, un programme devrait pouvoir fonctionner sans aucune option".

Le même principe pourrait être appliqué à mot-clé en Python. Ce type d'arguments doit permettre à l'utilisateur de "personnaliser" l'appel de la fonction, mais une fonction doit pouvoir être appelée sans aucune paire d'arguments implicites de type mot-clé-valeur.

0 votes

Alors... pourquoi Python 3 a-t-il ajouté un moyen d'avoir des arguments de type mot-clé requis ?

5 votes

def some_func(x, y, *, method, error='strict') -- method y error puede sólo être spécifié par mot-clé, et method doit être spécifié car il n'a pas de valeur par défaut.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X