Jaki jest cel pojedynczej zmiennej podkreślenia „_” w Pythonie?

618

Co oznacza _po forw tym kodzie?

if tbh.bag:
   n = 0
   for _ in tbh.bag.atom_set():
      n += 1
alwbtc
źródło
5
W twoim przypadku byłoby lepiej albo len(tbh.bag.atom_set())(jeśli zwrócona wartość ma __len__metodę) albosum(1 for _ in tbh.bag.atom_set())
Nick T
W pylintinnej opcji dla fałszywych nazw zmiennych jest prefiksem dummy_nazwy zmiennej. Użycie tego przedrostka z pylintpowoduje, że pylintnie emituje ostrzeżenia. Możesz także skonfigurować fałszywy wzorzec zmiennej, pylintaby dostosować go do takich rzeczy __.
Trevor Boyd Smith

Odpowiedzi:

780

_ ma 4 główne konwencjonalne zastosowania w Pythonie:

  1. Aby zatrzymać wynik ostatniego wykonanego wyrażenia (/ instrukcja) w interaktywnej sesji tłumacza. Ten precedens został ustanowiony przez standardowego tłumacza CPython, a inni tłumacze poszli w jego ślady
  2. Aby wyszukać tłumaczenie w i18n (zobacz na przykład dokumentację gettext ), jak w kodzie: raise forms.ValidationError(_("Please enter a correct username"))
  3. Jako ogólnego przeznaczenia „wyrzucenie” nazwa zmiennej, aby wskazać, że część wyniku funkcji jest celowo ignorowane (koncepcyjnej, jest on odrzucany.), Podobnie jak w kodzie, takich jak: label, has_label, _ = text.partition(':').
  4. Jako część definicji funkcji (przy użyciu albo deflub lambda), gdzie podpis jest ustalony (np. Przez wywołanie zwrotne lub API klasy nadrzędnej), ale ta konkretna implementacja funkcji nie wymaga wszystkich parametrów, jak w kodzie, takim jak:callback = lambda _: True

(Przez długi czas w tej odpowiedzi wymieniono tylko trzy pierwsze przypadki użycia, ale czwarty przypadek pojawiał się wystarczająco często, jak zaznaczono tutaj , aby był warty wyraźnego wypisania)

Ta ostatnia „zmienna jednorazowa zmienna lub nazwa parametru” może powodować konflikt z przypadkiem użycia odnośnika wyszukiwania translacji, dlatego należy unikać używania _jako zmiennej zmiennej w dowolnym bloku kodu, który również używa jej do tłumaczenia i18n (wielu ludzi woli podwójne podkreślenie , __jako ich zmienna odchodząca właśnie z tego powodu).

ncoghlan
źródło
19
Czy możesz wyjaśnić, jak to działa w wywołaniu funkcji, na przykład: raise forms.ValidationError (_ („Wprowadź poprawną nazwę użytkownika”)) . Widziałem to w kodzie Django i nie jest jasne, co się dzieje.
John C
41
To jest użycie 2 - zgodnie z konwencją, _jest to nazwa używana dla funkcji, która dokonuje wyszukiwania internacjonalizacji i translacji ciągów znaków lokalizacji. Jestem prawie pewien, że to gettextbiblioteka C ustanowiła tę konwencję.
ncoghlan
43
FWIW, osobiście zacząłem używać __(podwójnego podkreślenia) jako mojej zmiennej ogólnego przeznaczenia, aby uniknąć konfliktu z jednym z dwóch pierwszych przypadków użycia.
ncoghlan,
14
Wyłaniające się konwencje społeczności nie mają zwykle wiarygodnych źródeł - są to jedynie obserwacje praktyk, które pojawiły się z czasem. FWIW, jestem jednym ze współautorów nowszych aktualizacji PEP 8, a moja odpowiedź opiera się na 3 różnych sposobach, które widziałem _jako zmienne, odkąd zacząłem profesjonalnie używać Pythona w 2002 roku.
ncoghlan
12
Konwencja dotyczy głównie rozpakowywania krotek: a, __, c = iterablenatychmiast informuje czytelnika, że ​​rozpakowujemy krotkę 3-krotną, ale tylko przy użyciu pierwszej i ostatniej wartości. Gdybyśmy zamiast pisać a, b, c = iterable, czytelnik (lub zautomatyzowany kod linter) można oczekiwać wszystkich a, bi cdo późniejszego wykorzystania (a jeśli nie, to może być oznaką czegoś bug).
ncoghlan
207

Jest to po prostu nazwa zmiennej i jest ona powszechnie stosowana w pythonie do używania _zmiennych zmiennych. Wskazuje tylko, że zmienna pętli nie jest faktycznie używana.

gsteff
źródło
5
masz na myśli, że nie reprezentuje on ostatniej zwróconej wartości?
alwbtc
31
@steve tylko w powłoce
Gabi Purcaru
4
podobny do użycia _ w Prologu
Matthias
3
podobny do użycia ~ w Matlabie
PatriceG
Zauważ, że w powłoce cpython, jeśli wyraźnie ją zdefiniujesz _, na stałe przestanie utrzymywać wartość wyjściową poprzedniego wyrażenia. Wydaje się to okropnie niespójne, a standardy języka Python muszą rozwiązać ten problem. Powinni po prostu zdefiniować, _że jest to nazwa, którą można odrzucić, i nie używać jej jako prawdziwego identyfikatora.
theferrit32
78

Podkreślenie _jest uważane za zmienną „ Nie obchodzi mnie ” lub „ Wyrzucanie ” w Pythonie

  • Interpretator python przechowuje ostatnią wartość wyrażenia w specjalnej zmiennej o nazwie _.

    >>> 10 
    10
    
    >>> _ 
    10
    
    >>> _ * 3 
    30
  • Podkreślenie _służy także do ignorowania określonych wartości. Jeśli nie potrzebujesz określonych wartości lub wartości nie są używane, po prostu przypisz te wartości do podkreślenia.

    Zignoruj ​​wartość podczas rozpakowywania

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

    Zignoruj ​​indeks

    for _ in range(10):     
        do_something()
Ashish Sahu
źródło
2
Trzecie zastosowanie dotyczy funkcji internacjonalizacji _("Hello world!").
Jeff Younker
3
Na poziomie procesora, czy faktycznie istnieje różnica między „for _ in range” i „for x in range”, a następnie nie używa x? Czy jest to tylko dla czytelności człowieka?
iammax,
1
@iammax Używając dismodułu odkryłem, że nie było różnicy w kodzie bajtowym. Korzyści z czytelności dla ludzi są jednak oczywiste.
Alistair Carscadden,
21

Istnieje 5 przypadków użycia podkreślenia w Pythonie.

  1. Do przechowywania wartości ostatniego wyrażenia w tłumaczu.

  2. Za ignorowanie określonych wartości. (tak zwane „nie dbam”)

  3. Nadać specjalne znaczenia i funkcje nazwom vartiables lub funkcji.

  4. Używać jako funkcji „internacjonalizacji (i18n)” lub „lokalizacji (l10n)”.

  5. Aby oddzielić cyfry liczby literalnej.

Oto fajny artykuł z przykładami autorstwa mingrammer .

Troszczyć się
źródło
2
W rzeczywistości jest to całkiem nowy blog.pythonlibrary.org/2017/01/11/...
MichaelChirico
3

Jeśli chodzi o języki Python, _nie ma specjalnego znaczenia. Jest to ważny identyfikator jak _foo, foo_lub _f_o_o_.

Każde specjalne znaczenie _ma wyłącznie konwencję. Kilka przypadków jest powszechnych:

  • Nazwa fikcyjna, gdy zmienna nie jest przeznaczona do użycia, ale nazwa jest wymagana przez składnię / semantykę.

    # iteration disregarding content
    sum(1 for _ in some_iterable)
    # unpacking disregarding specific elements
    head, *_ = values
    # function disregarding its argument
    def callback(_): return True
  • Wiele REPL / powłok przechowuje wyniki ostatniego wyrażenia najwyższego poziomu na builtins._ .

    Specjalny identyfikator _ jest używany w interaktywnym tłumaczu do przechowywania wyniku ostatniej oceny; jest przechowywany w builtinsmodule. Gdy nie jest w trybie interaktywnym, _nie ma specjalnego znaczenia i nie jest zdefiniowane. [ źródło ]

    Ze względu na sposób wyszukiwania nazw, chyba że jest to cień globalny lub lokalny _ definicji, do której _odnosi się nagi 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

    Uwaga: Niektóre powłoki, takie jak ipythonnie przypisywane do builtins._specjalnych przypadków _.

  • W kontekście internacjonalizacja i lokalizacja _jest używana jako alias dla podstawowej funkcji tłumaczenia.

    gettext.gettext (wiadomość)

    Zwraca zlokalizowane tłumaczenie wiadomości na podstawie bieżącej globalnej domeny, języka i katalogu ustawień regionalnych. Ta funkcja jest zwykle aliasowana jako _ () w lokalnej przestrzeni nazw (patrz przykłady poniżej).

MisterMiyagi
źródło