Comment nommer des fonctions qui renvoient des valeurs en Python?

13

Je suis confus quant au choix des noms pour mes fonctions en Python . Parfois, les fonctions intégrées Python sont impératives telles que: printfonction et méthode de chaîne find. Parfois, ils ne sont pas tels que: lenson nom n'est pas impératif comme calculate_len, par exemple, et typene l'est pas find_type.

Je peux comprendre que printrenvoie une valeur que nous n'utilisons pas (c'est-à-dire None) et fait quelque chose (c'est-à-dire qu'il montre une chaîne à l'écran), donc son nom est impératif.

Mais lenrenvoie une valeur que nous utilisons et fait quelque chose (c'est-à-dire calculer le nombre d'éléments dans une séquence ou un mappage) et son nom n'est pas impératif . D'un autre côté, findla méthode string (as len) renvoie une valeur que nous utilisons et fait quelque chose, et son nom est impératif .

Ce qui a fait poser cette question, c'est que j'ai mis à jour un script qui crypte et décrypte la chaîne en utilisant le chiffrement César. Le critique a déclaré que:

Juste une intuition: les fonctions font des choses. Donc, un bon nom pour une fonction est un impératif: j'utiliserais à la rotate_letterplace de rotated_letter.

rotated_letterrenvoie une chaîne d'une seule lettre représentant une lettre tournée d'un nombre. Je ne sais pas ce qui est mieux, je l'ai utilisé rotated_lettercar il renvoie une valeur, comme la randintfonction dans un module aléatoire , ce n'est pas le cas generate_randint.

Donc, dans ce cas, comment dois-je nommer une fonction qui renvoie une valeur à utiliser? Dois-je rendre le nom impératif ou juste un nom . Dans d'autres cas, il est évident de savoir comment le faire, comme les fonctions booléennes , comme is_evenet is_palindromenous le faisons simplement comme une question oui / non , et aussi des fonctions qui font et renvoient simplement des valeurs non utilisées (c.-à-d. None), Comme la printméthode list sort.

Mahmood Muhammad Nageeb
la source
c'est en fait une pratique très courante (je dirais une convention) d'utiliser des impératifs lors de la dénomination de la fonction. Par exemple, comment nommez-vous une variable qui stocke la lettre pivotée de la fonction rotated_letter?
JoulinRouge
Ce n'est pas une bonne façon de penser à certains de vos exemples. len, par exemple, est mieux considéré comme une "longueur de" - vous obtenez une description au niveau méta de son argument.
Izkata

Réponses:

10

Utilisez des verbes lorsqu'ils sont raisonnables, des noms s'ils sont plus courts et sans ambiguïté

La plupart du temps, les fonctions doivent être des verbes (impératifs) et les classes, les variables et les paramètres doivent être des noms. Les attributs doivent également être des noms, y compris ceux créés à l'aide de @property. C'est particulièrement le cas pour les fonctions qui ont des effets secondaires. [1] Si une fonction retourne quelque chose, vous devez évaluer si le verbe ajoute quelque chose ou est juste du "bruit":

  • make_list(foo)vs list(foo): Le nom est plus facile à lire que le verbe. Aussi, listest en fait une classe, et les classes doivent être des noms.
  • open(foo)vs file(foo).: Le verbe est plus facile à lire que le nom, et il est plus logique de donner des "options" à un verbe qu'à un nom, donc le nom a été supprimé en Python 3. open()reste la seule façon "standard" [2] pour créer des objets fichier dans Python 3.
  • foo.get_bar()vs foo.bar()vs foo.bar(supposez fooet barsont tous deux des noms): La première option est tout de suite sortie, car le «get» n'ajoute rien que nous ne connaissions déjà. Le second est approprié si l' obtention d' un bard'un fooest une opération potentiellement coûteuse et / ou porte des effets secondaires (vous pouvez également envisager Bar(foo)si Barest une classe). Le troisième est approprié s'il s'agit d'une opération bon marché sans effets secondaires et qu'il est peu probable que des implémentations alternatives la rendent coûteuse .
  • xs.sort()vs sorted(xs)si xsest une liste: La première est impérative: Triez la liste. Il modifie la liste sur place et ne renvoie rien. La seconde est déclarative: une liste qui est triée, c'est précisément ce qu'elle renvoie. Les deux sont des verbes.

[1]: Habituellement, le retour d'une valeur et les effets secondaires s'excluent mutuellement, sauf si vous avez une raison impérieuse de les combiner. Donc, une fonction qui a des effets secondaires ne devrait probablement rien renvoyer et donc en faire un nom n'aurait que très peu de sens.
[2]: Il y a quelques opérations de niveau modérément inférieur dans le iomodule qui peuvent être utilisées pour ajouter ou supprimer la mise en mémoire tampon de fichiers, le texte automatique en / décodage, etc., et ce sont principalement des noms car ce sont des classes orientées objet. La plupart des utilisateurs n'ont pas besoin de jouer directement avec ces choses; au lieu de cela, open()choisit une classe appropriée et l'instancie automatiquement.

Kevin
la source
Je vous remercie! Dans " foo.get_bar() vs` foo.bar ()` vs foo.bar" quelle est la différence entre le deuxième et le troisième ?
Mahmood Muhammad Nageeb
Le troisième est soit une propriété soit un attribut nu. Le second est une méthode.
Kevin
Donc, si je comprends bien, il convient de ne pas rendre rotated_letterimpératif et de le garder déclaratif, non?
Mahmood Muhammad Nageeb
Dans ce cas, je ne sais pas si cela letterest impliqué par le contexte.
Kevin
+1 pour mentionner listest une classe
Dušan Maďar
0

rotated_letterne ressemble pas à une méthode. Cela ressemble à une propriété. Ce qui signifie que la première idée est de faire:

var letter = caesar.rotated_letter

s'attendant letterà contenir une valeur de type chaîne, pas une fonction. À partir de là, vous avez choisi un nom différent, tel que:

def rotate_letter(self):
    pass

ou vous utilisez une propriété à la place:

@property
def rotated_letter(self):
    return self.whatever

lenet typesont nommés ainsi car tout autre nom serait long à taper. Ils sont beaucoup utilisés, et ils ont un statut spécial des fonctions Python de base que chaque programmeur Python apprendra de toute façon, rendant leurs noms beaucoup plus inutiles que les noms de bibliothèques tierces.

len, en particulier, est un bon exemple de ce que vous ne devriez pas faire dans votre code: vous devez utiliser des noms complets tels que length(sauf si la forme courte est très populaire, par exemple max), et utiliser un verbe, tel que compute_length. Ou ce pourrait être une propriété: len([1, 5, 6])devient [1, 5, 6].length. Par exemple, en C #, la forme est utilisée plus tard: new [] { ... }.Length.

Notez qu'il peut également y avoir des raisons historiques pour len: d'autres langages, tels que C #, préféré Count, qui est généralement une méthode (bien que le comportement soit malheureusement incohérent via .NET Framework). Countest un verbe, donc intuitivement, vous êtes enclin à l'invoquer comme méthode.

Renvoyer des valeurs ou effectuer une action

Une fonction est toujours censée exécuter une action. S'il renvoie à peine une valeur, il doit s'agir d'une propriété. Vous avez un indice que la fonction doit être transformée en propriété lorsque:

  • La fonction contient à peine une return ...instruction,

  • Le nom de la fonction qui vous vient naturellement à l'esprit est get_something, comme dans product.get_price().

Maintenant, si vous avez une fonction, elle peut être de quatre types:

  • Il peut être pur, c'est-à-dire renvoyer une valeur sans affecter l'environnement. Exemple: road.measure_distance().

  • Il peut affecter l'environnement sans rien retourner. Exemple: product_database.remove_record(1234).

  • Il peut affecter l'environnement et renvoyer une valeur. Exemple: value.increment()utilisé tel que value++.

  • Il ne peut rien faire et ne rien retourner. Exemple: time.sleep(1).

Il y a peu de cas où le nom pourrait donner une indication forte sur le type de la fonction, mais dans de nombreux cas, vous ne pourrez pas à peine connaître le type à partir de son nom.

Arseni Mourzenko
la source
Je suppose que la réponse est "oui", mais je dois demander: répondez-vous entièrement du point de vue de Python? Parce que dans d'autres langues, votre séparation fonction / propriété n'est pas toujours vraie; il n'est pas vrai non plus qu'une fonction "doive effectuer une action". Est-ce la convention en Python? (J'écris Python mais je n'ai pas lu tous les PEP et je ne suis certainement PAS un expert. Je n'ai pas dévalorisé, BTW).
Andres F.
@AndresF.: Je réponds du point de vue de Python. Dans des langages tels que Java où les propriétés n'existent pas getSomethinget setSomethingsont les noms habituels utilisés à la place des propriétés.
Arseni Mourzenko