Quel est le but de la variable de soulignement unique «_» en Python?

618

Quelle est la signification d’ _après fordans ce code?

if tbh.bag:
   n = 0
   for _ in tbh.bag.atom_set():
      n += 1
alwbtc
la source
5
Pour votre cas, il serait plus propre de len(tbh.bag.atom_set())(si la valeur retournée a une __len__méthode) ousum(1 for _ in tbh.bag.atom_set())
Nick T
Dans pylintune autre option pour les noms de variables factices, il y a un préfixe dummy_pour le nom de variable. L'utilisation de ce préfixe avec pylint, pylintn'émet pas d'avertissement. Vous pouvez également configurer le modèle de variable factice pour pylints'adapter à des choses comme __.
Trevor Boyd Smith

Réponses:

781

_ a 4 utilisations conventionnelles principales en Python:

  1. Pour conserver le résultat de la dernière expression exécutée (instruction /) dans une session d'interpréteur interactif. Ce précédent a été créé par l'interpréteur CPython standard, et d'autres interprètes ont emboîté le pas
  2. Pour la recherche de traduction dans i18n (voir la documentation gettext par exemple), comme dans le code comme: raise forms.ValidationError(_("Please enter a correct username"))
  3. En usage général « jetable » nom de la variable pour indiquer qu'une partie d'un résultat de la fonction est délibérément ignoré (Conceptuellement, il est mis au rebut.), Comme dans le code comme: label, has_label, _ = text.partition(':').
  4. Dans le cadre d'une définition de fonction (en utilisant soit defou lambda), où la signature est fixée (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 comme:callback = lambda _: True

(Pendant longtemps, cette réponse n'a énuméré que les trois premiers cas d'utilisation, mais le quatrième cas est apparu assez souvent, comme indiqué ici , pour mériter une liste explicite)

Les derniers cas d'utilisation de "variable jetable ou nom de paramètre" peuvent entrer en conflit avec le cas d'utilisation de recherche de traduction, il est donc nécessaire d'éviter d'utiliser _comme variable jetable dans tout bloc de code qui l'utilise également pour la traduction i18n (de nombreuses personnes préfèrent un double soulignement , __comme leur variable jetable précisément pour cette raison).

ncoghlan
la source
19
Pourriez-vous expliquer comment cela fonctionne dans un appel de fonction, par exemple: raise forms.ValidationError (_ ("Veuillez saisir un nom d'utilisateur correct")) . J'ai vu cela dans le code Django, et ce qui se passe n'est pas clair.
John C
41
Il s'agit de l'utilisation 2 - par convention, _est le nom utilisé pour la fonction qui effectue les recherches de traduction de chaînes d'internationalisation et de localisation. Je suis presque sûr que c'est la gettextbibliothèque C qui a établi cette convention.
ncoghlan
43
FWIW, j'ai personnellement commencé à utiliser __(un double trait de soulignement) comme variable jetable à usage général pour éviter tout conflit avec l'un des deux premiers cas d'utilisation.
ncoghlan
14
Les conventions communautaires émergentes n'ont pas tendance à avoir des sources faisant autorité - juste des observations des pratiques qui sont apparues au fil du temps. FWIW, je suis l'un des co-auteurs de mises à jour plus récentes de PEP 8, et ma réponse est basée sur les 3 façons différentes que j'ai vues _utilisées comme nom de variable depuis que j'ai commencé à utiliser Python professionnellement en 2002.
ncoghlan
12
La convention concerne principalement le décompactage de tuple: a, __, c = iterableindique immédiatement au lecteur que nous décompressons un triplet, mais uniquement en utilisant les première et dernière valeurs. Si l' on place écrire a, b, c = iterable, le lecteur (ou un code automatisé linter) peut raisonnablement attendre tous a, bet cà utiliser plus tard (et si elles ne sont pas, il peut être un signe d'un endroit bug).
ncoghlan
207

C'est juste un nom de variable, et il est classique en python à utiliser _pour les variables jetables. Cela indique simplement que la variable de boucle n'est pas réellement utilisée.

gsteff
la source
5
vous voulez dire qu'il ne représente pas la dernière valeur renvoyée?
alwbtc
31
@steve uniquement dans un shell
Gabi Purcaru
4
similaire à l'utilisation de _ dans Prolog
Matthias
3
similaire à l'utilisation de ~ dans Matlab
PatriceG
Notez que dans le shell cpython si vous définissez explicitement _, il arrête définitivement de conserver la valeur de sortie de l'expression précédente. Cela semble horriblement incohérent, et les normes Python lang doivent y remédier. Ils doivent simplement définir _comme un nom jetable et l'empêcher d'être utilisé comme véritable identifiant.
theferrit32
78

Le soulignement _est considéré comme une variable " Je m'en fiche " ou " Throwaway " 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
  • Le trait de soulignement _est également utilisé pour ignorer les valeurs spécifiques. Si vous n'avez pas besoin des valeurs spécifiques ou si les valeurs ne sont pas utilisées, affectez simplement les valeurs au trait de soulignement.

    Ignorer une valeur lors du déballage

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

    Ignorer l'index

    for _ in range(10):     
        do_something()
Ashish Sahu
la source
2
Il y a une troisième utilisation, qui concerne la fonction d'internationalisation _("Hello world!").
Jeff Younker
3
Au niveau du processeur, existe-t-il réellement une différence entre "for _ in range" et "for x in range" et ne pas utiliser x? Ou est-ce juste pour la lisibilité humaine?
iammax
1
@iammax En utilisant le dismodule, j'ai trouvé qu'il n'y avait aucune différence dans le bytecode. Les avantages de la lisibilité humaine sont cependant évidents.
Alistair Carscadden
21

Il existe 5 cas d'utilisation du trait de soulignement en Python.

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

  2. Pour ignorer les valeurs spécifiques. (soi-disant «je m'en fiche»)

  3. Donner des significations et des fonctions spéciales au nom des vartiables ou des fonctions.

  4. A utiliser comme fonctions «Internationalisation (i18n)» ou «Localisation (l10n)».

  5. Pour séparer les chiffres de la valeur littérale du nombre.

Voici un bel article avec des exemples de mingrammer .

Reck
la source
2
En fait, c'est un tout nouveau blog.pythonlibrary.org/2017/01/11/…
MichaelChirico
3

En ce qui concerne les langages Python, _n'a pas de signification particulière. C'est un identifiant valide comme _foo, foo_ou _f_o_o_.

Toute signification particulière de _est purement conventionnelle. Plusieurs cas sont courants:

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

    # iteration disregarding content
    sum(1 for _ in some_iterable)
    # unpacking disregarding specific elements
    head, *_ = values
    # function disregarding its argument
    def callback(_): return True
  • De nombreux 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 builtinsmodule. Lorsqu'il n'est pas en mode interactif, _n'a pas de signification particulière et n'est pas défini. [ source ]

    En raison de la façon dont les noms sont recherchés, à moins qu'ils ne soient masqués par une _définition globale ou locale, le nu _fait référence builtins._.

    >>> 42
    42
    >>> f'the last answer is {_}'
    'the last answer is 42'
    >>> _
    'the last answer is 42'
    >>> _ = 4  # shadow ``builtins._`` with global ``_``
    >>> 23
    23
    >>> _
    4

    Remarque: certains shells tels que ceux qui ipythonne sont pas attribués builtins._mais dans un cas spécial _.

  • Dans le contexte internationalisation et localisation, _est utilisé comme alias pour la fonction de traduction principale.

    gettext.gettext (message)

    Renvoie la traduction localisée du message, en fonction du domaine global actuel, de la langue et du répertoire local. Cette fonction est généralement aliasée _ () dans l'espace de noms local (voir les exemples ci-dessous).

MonsieurMiyagi
la source