784 votes

Quel est le but de la variable de soulignement "_" en Python?

Quelle est la signification de _ après for dans ce code?

if tbh.bag:
    n = 0
    for _ in tbh.bag.atom_set():
        n += 1

7 votes

Pour votre cas, il serait plus propre d'utiliser soit len(tbh.bag.atom_set()) (si la valeur retournée a une méthode __len__) ou sum(1 for _ in tbh.bag.atom_set())

0 votes

Dans pylint, une autre option pour les noms de variables bidons est un préfixe de dummy_ pour le nom de la variable. En utilisant ce préfixe avec pylint, cela empêche pylint d'émettre un avertissement. Vous pouvez également configurer le motif de variable bidon pour pylint pour prendre en compte des choses comme __.

995voto

ncoghlan Points 10779

_ a 3 utilisations conventionnelles principales en Python :

  1. Pour contenir le résultat de la dernière expression exécutée dans une session interactive interpréteur (voir docs). Ce précédent a été établi par l'interpréteur standard CPython et d'autres interprètes ont suivi le mouvement

  2. Pour la recherche de traduction en i18n (voir la gettext documentation par exemple), comme dans le code suivant

    raise forms.ValidationError(_("Veuillez entrer un nom d'utilisateur correct"))
  3. Comme un nom de variable "jetable" à usage général :

    1. Pour indiquer qu'une partie du résultat d'une fonction est délibérément ignorée (Conceptuellement, elle est rejetée), comme dans le code suivant :

      label, has_label, _ = text.partition(':')
    2. Comme partie d'une définition de fonction (utilisant soit def soit lambda), où la signature est fixe (par exemple par un rappel ou une API de classe parent), mais cette implémentation de fonction particulière n'a pas besoin de tous les paramètres, comme dans le code suivant :

      def rappel(_):
          return True

      [Pendant longtemps, cette réponse ne mentionnait pas ce cas d'utilisation, mais il est apparu assez souvent, comme indiqué ici, pour mériter d'être listé explicitement.]

    Ce cas d'utilisation peut entrer en conflit avec le cas d'utilisation de recherche de traduction, il est donc nécessaire d'éviter d'utiliser _ comme nom de variable jetable dans tout bloc de code qui l'utilise également pour la traduction i18n (beaucoup de gens préfèrent un double tiret bas, __, comme leur nom de variable jetable pour cette raison).

    Les linter reconnaissent souvent ce cas d'utilisation. Par exemple, année, mois, jour = date() générera un avertissement linter si jour n'est pas utilisé plus tard dans le code. La solution, si jour n'est vraiment pas nécessaire, est d'écrire année, mois, _ = date(). De même avec les fonctions lambda, lambda arg: 1.0 crée une fonction nécessitant un argument mais ne l'utilisant pas, ce qui sera détecté par le linter. La solution est d'écrire lambda _: 1.0. Une variable inutilisée cache souvent un bug/une faute de frappe (par exemple, définir jour mais utiliser dya à la ligne suivante).

    La fonctionnalité de correspondance de motifs ajoutée dans Python 3.10 a élevé cette utilisation de "convention" à "syntaxe de langage" en ce qui concerne les déclarations match : dans les cas de correspondance, _ est un motif générique, et l'exécution ne lie même pas une valeur au symbole dans ce cas.

    Pour d'autres cas d'utilisation, n'oubliez pas que _ reste un nom de variable valide, et donc garde toujours des objets en vie. Dans les cas où cela est indésirable (par exemple pour libérer de la mémoire ou des ressources externes), un appel explicite del nom satisfera à la fois les linters indiquant que le nom est utilisé, et effacera promptement la référence à l'objet.

24 votes

Pouvez-vous expliquer comment cela fonctionne dans un appel de fonction, par exemple : raise forms.ValidationError(_("Veuillez entrer un nom d'utilisateur correct")). J'ai vu cela dans le code Django, et ce n'est pas clair ce qui se passe.

44 votes

Ceci est l'utilisation 2 - par convention, _ est le nom utilisé pour la fonction qui effectue des recherches de traduction de chaînes pour l'internationalisation et la localisation. Je suis assez sûr que c'est la bibliothèque C gettext qui a établi cette convention.

50 votes

FWIW, j'ai personnellement commencé à utiliser __ (un double tiret bas) comme ma variable jetable générale pour éviter les conflits avec les deux premiers cas d'utilisation.

253voto

gsteff Points 1674

C'est simplement un nom de variable, et il est conventionnel en python d'utiliser _ pour les variables jetables. Cela indique simplement que la variable de boucle n'est pas réellement utilisée.

7 votes

Tu veux dire que cette valeur ne représente pas la dernière valeur retournée?

40 votes

@steve seulement dans une coquille python

4 votes

Similaire à l'utilisation de _ en Prolog

133voto

Ashish Sahu Points 917

Souligné _ est considéré comme variable "Je m'en fiche" ou "jetable" en Python

  • L'interpréteur Python stocke la dernière valeur d'expression dans la variable spéciale appelée _.

    >>> 10
    10
    
    >>> _
    10
    
    >>> _ * 3
    30
  • L'underscore _ est également utilisé pour ignorer des valeurs spécifiques. Si vous n'avez pas besoin des valeurs spécifiques ou si les valeurs ne sont pas utilisées, attribuez simplement les valeurs à l'underscore.

    Ignorer une valeur lors du dépaquetage

    x, _, y = (1, 2, 3)
    
    >>> x
    1
    
    >>> y
    3

    Ignorer l'index

    for _ in range(10):
        faire_quelque_chose()

3 votes

Il y a un troisième usage, qui est pour la fonction d'internationalisation _ ("Hello world!").

11 votes

Au niveau du processeur, y a-t-il réellement une différence entre "for _ in range" et "for x in range" et ensuite ne pas utiliser x? Ou est-ce simplement pour la lisibilité humaine?

10 votes

@iammax En utilisant le module dis, j'ai trouvé qu'il n'y avait aucune différence dans le bytecode. Les avantages de la lisibilité humaine sont évidents, cependant.

33voto

Reck Points 908

Il existe 5 cas d'utilisation du tiret bas en Python.

  1. Pour stocker la valeur de la dernière expression dans l'interpréteur.

  2. Pour ignorer des valeurs spécifiques. (appelées "je m'en fiche")

  3. Pour donner des significations et fonctions spéciales au nom des variables ou fonctions.

  4. Pour utiliser comme fonctions 'internationalisation (i18n)' ou 'localisation (l10n)’.

  5. Pour séparer les chiffres de la valeur littérale d'un nombre.

Ici se trouve un bel article avec des exemples de mingrammer.

2 votes

En fait, c'est assez nouveau blog.pythonlibrary.org/2017/01/11/…

2 votes

Les numéros 3 et 5 ne s'appliquent pas vraiment à cette question. L'OP demande un simple soulignement en tant que nom autonome, mais le point 3 parle de l'utilisation de soulignements comme partie d'un plus grand nom, et le point 5 parle de son utilisation dans un sens littéral, pas en tant que nom. Je mentionne juste au cas où des nouveaux soient confus. Il pourrait être utile de modifier la réponse pour le clarifier.

13voto

MisterMiyagi Points 2734

En ce qui concerne le langage Python, _ n'a généralement pas de signification spéciale. C'est un identifiant valide tout comme _foo, foo_ ou _f_o_o_.
La seule exception concerne les instructions match depuis Python 3.10 :

Dans un motif case au sein d'une instruction match, _ est un mot-clé souple qui représente un joker. source

Autrement, toute signification particulière de _ est purement conventionnelle. Plusieurs cas sont courants :

  • Un nom fictif lorsque qu'une variable n'est pas destinée à être utilisée, mais qu'un nom est requis par la syntaxe/sémantique.

    # itération en ignorant le contenu
    sum(1 for _ in some_iterable)
    # déballage en ignorant des éléments spécifiques
    head, *_ = values
    # fonction ignorant son argument
    def callback(_): return True
  • Beaucoup de REPL/shells stockent le résultat de la dernière expression de niveau supérieur dans builtins._.

    L'identifiant spécial _ est utilisé dans l'interpréteur interactif pour stocker le résultat de la dernière évaluation ; il est stocké dans le module builtins. Lorsque ce n'est pas en mode interactif, _ n'a pas de signification spéciale et n'est pas défini. [source]

    En raison de la façon dont les noms sont recherchés, sauf s'ils sont occultés par une définition globale ou locale de _, le simple _ fait référence à builtins._.

    >>> 42
    42
    >>> f'la dernière réponse est {_}'
    'la dernière réponse est 42'
    >>> _
    'la dernière réponse est 42'
    >>> _ = 4  # occulter ``builtins._`` avec ``_`` global
    >>> 23
    23
    >>> _
    4

    Remarque : Certains shells comme ipython n'assignent pas à builtins._ mais traitent _ de manière spéciale.

  • Dans le contexte de l'internationalisation et de la localisation, _ est utilisé comme un alias pour la fonction de traduction principale.

    gettext.gettext(message)

    Retourne la traduction localisée du message, basée sur le domaine, la langue et le répertoire de localisation global actuels. Cette fonction est généralement renommée en _() dans l'espace de noms local (voir exemples ci-dessous).

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