Je suis confus quant au choix des noms pour mes fonctions dans Python. Parfois Python les fonctions intégrées sont impératives telles que: print
fonction et méthode de chaîne find
. Parfois, ils ne sont pas tels que: len
son nom n'est pas impératif tel que calculate_len
, par exemple, et type
n'est pas find_type
.
Je peux comprendre que print
renvoie une valeur que nous n'utilisons pas (c'est-à-dire None
) et fait quelque chose (c'est-à-dire qu'il affiche une chaîne à l'écran), donc son nom est impératif.
Mais len
renvoie 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é, la méthode de chaîne find
(comme 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
rotate_letter
au lieu derotated_letter
.
rotated_letter
renvoie une chaîne d'une seule lettre représentant une lettre tournée d'un nombre. Je ne sais pas ce qui est mieux, j'ai utilisé rotated_letter
car il renvoie une valeur, comme la fonction randint
dans module aléatoire, ce n'est pas generate_randint
.
Donc, dans ce cas, comment dois-je nommer une fonction qui renvoie une valeur à utiliser? Dois-je faire le nom impératif ou juste un nom. Dans d'autres cas, il est évident de le faire, comme fonctions booléennes, comme is_even
et is_palindrome
nous le faisons juste comme un question oui/non, et aussi des fonctions qui font juste et retournent des valeurs non utilisées (ie None
), comme print
et lister la méthode sort
.
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. De plus, list
est 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é dans Python 3. open()
reste le seul moyen "standard" [2] de créer des objets fichier dans Python 3.foo.get_bar()
vs foo.bar()
vs foo.bar
(supposons que foo
et bar
sont tous deux des noms): la première option est tout de suite , car le "get" n'ajoute rien que nous ne connaissions déjà. La seconde est appropriée si l'extraction d'un bar
d'un foo
est une opération potentiellement coûteuse et/ou comporte des effets secondaires (vous pouvez également envisager Bar(foo)
if Bar
est une classe). Le troisième est approprié s'il s'agit d'une opération bon marché sans effets secondaires, et les implémentations alternatives sont peu susceptibles de le rendre cher.xs.sort()
vs sorted(xs)
si xs
est 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]: Le module io
contient des opérations de niveau modérément inférieur qui peuvent être utilisées pour ajouter ou supprimer la mise en mémoire tampon des fichiers, le texte automatique en/décodage, etc. les noms car ce sont des classes orientées objet. La plupart des utilisateurs n'ont pas besoin de jouer directement avec ces choses; à la place, open()
choisit une classe appropriée et l'instancie automatiquement.
rotated_letter
Ne 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
attendre que letter
contienne 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
len
et type
sont nommés ainsi car tout autre nom serait long à taper. Ils sont beaucoup utilisés et ont un statut spécial de noyau Python fonctions que chaque Python programmeur 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 le code votre: vous êtes censé utiliser des noms complets tels que length
(sauf si le la forme courte est très populaire, comme max
), et utilisez un verbe, comme compute_length
. Ou cela pourrait être une propriété: len([1, 5, 6])
devient [1, 5, 6].length
. Par exemple, en C #, la dernière forme est utilisée: 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). Count
est un verbe, donc intuitivement, vous êtes enclin à l'invoquer comme méthode.
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 instruction return ...
,
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.