Apa tujuan dari variabel “_” garis bawah tunggal dalam Python?

618

Apa artinya _setelah fordalam kode ini?

if tbh.bag:
   n = 0
   for _ in tbh.bag.atom_set():
      n += 1
alwbtc
sumber
5
Untuk kasus Anda, akan lebih baik len(tbh.bag.atom_set())jika (jika nilai yang dikembalikan memiliki __len__metode) atausum(1 for _ in tbh.bag.atom_set())
Nick T
Dalam pylintopsi lain untuk nama variabel dummy adalah awalan dummy_untuk nama variabel. Menggunakan awalan ini dengan pylint, membuat pylinttidak memancarkan peringatan. Anda juga dapat mengkonfigurasi pola variabel dummy untuk pylintmengakomodasi hal-hal seperti __.
Trevor Boyd Smith

Jawaban:

780

_ memiliki 4 penggunaan konvensional utama dalam Python:

  1. Untuk menahan hasil dari ekspresi (/ pernyataan) yang terakhir dieksekusi dalam sesi juru bahasa interaktif. Preseden ini ditetapkan oleh juru bahasa CPython standar, dan penerjemah lain mengikuti
  2. Untuk pencarian terjemahan di i18n (lihat dokumentasi gettext misalnya), seperti dalam kode seperti: raise forms.ValidationError(_("Please enter a correct username"))
  3. Sebagai tujuan umum "sekali pakai" nama variabel untuk menunjukkan bahwa bagian dari hasil fungsi sedang sengaja diabaikan (konseptual, itu sedang dibuang.), Seperti dalam kode seperti: label, has_label, _ = text.partition(':').
  4. Sebagai bagian dari definisi fungsi (menggunakan salah satu defatau lambda), di mana tanda tangan diperbaiki (mis. Dengan callback atau API kelas induk), tetapi implementasi fungsi khusus ini tidak memerlukan semua parameter, seperti dalam kode seperti:callback = lambda _: True

(Untuk waktu yang lama jawaban ini hanya mencantumkan tiga kasus penggunaan pertama, tetapi kasus keempat cukup sering muncul, seperti yang disebutkan di sini , layak dicantumkan secara eksplisit)

"Variabel variabel atau nama parameter" yang terakhir menggunakan kasus dapat bertentangan dengan kasus penggunaan pencarian terjemahan, jadi perlu untuk menghindari menggunakan _sebagai variabel sekali pakai dalam blok kode apa pun yang juga menggunakannya untuk terjemahan i18n (banyak orang lebih suka garis bawah dua kali lipat) ,, __sebagai variabel sekali pakai mereka untuk alasan ini).

ncoghlan
sumber
19
Bisakah Anda menjelaskan cara kerjanya dalam panggilan fungsi, misalnya: naikkan forms.ValidationError (_ ("Silakan masukkan nama pengguna yang benar")) . Saya telah melihat ini dalam kode Django, dan tidak jelas apa yang terjadi.
John C
41
Itu adalah penggunaan 2 - oleh konvensi, _adalah nama yang digunakan untuk fungsi yang melakukan pencarian terjemahan string internasionalisasi dan lokalisasi. Saya cukup yakin itu adalah gettextperpustakaan C yang menetapkan konvensi itu.
ncoghlan
43
FWIW, saya pribadi mulai menggunakan __(garis bawah ganda) sebagai variabel tujuan umum saya untuk menghindari konflik dengan salah satu dari dua kasus penggunaan pertama.
ncoghlan
14
Konvensi-konvensi komunitas yang muncul tidak cenderung memiliki sumber otoritatif - hanya pengamatan terhadap praktik-praktik yang telah muncul seiring waktu. FWIW, saya salah satu penulis bersama pembaruan PEP 8 terbaru, dan jawaban saya didasarkan pada 3 cara berbeda yang saya lihat _digunakan sebagai nama variabel sejak saya mulai menggunakan Python secara profesional pada tahun 2002.
ncoghlan
12
Konvensi ini terutama untuk membongkar tuple: a, __, c = iterablememberi tahu pembaca segera bahwa kami membongkar tuple 3, tetapi hanya menggunakan nilai pertama dan terakhir. Jika kita alih-alih menulis a, b, c = iterable, pembaca (atau kode linter otomatis) bisa berharap semua a, bdan cakan digunakan kemudian (dan jika mereka tidak, mungkin menjadi tanda dari suatu tempat bug).
ncoghlan
207

Itu hanya nama variabel, dan itu konvensional dalam python digunakan _untuk variabel throwaway. Ini hanya menunjukkan bahwa variabel loop tidak benar-benar digunakan.

Gsteff
sumber
5
Anda berarti itu tidak mewakili nilai yang dikembalikan terakhir?
alwbtc
31
@steve hanya dalam cangkang
Gabi Purcaru
4
mirip dengan penggunaan _ dalam Prolog
Matthias
3
mirip dengan penggunaan ~ in Matlab
PatriceG
Perhatikan bahwa dalam cpython shell jika Anda secara eksplisit mendefinisikannya _, ia secara permanen berhenti memegang nilai output dari ekspresi sebelumnya. Ini tampaknya sangat tidak konsisten, dan standar lang Python perlu mengatasi ini. Mereka hanya harus mendefinisikan _sebagai nama sekali pakai dan menghentikannya agar tidak digunakan sebagai pengidentifikasi nyata.
theferrit32
78

Garis bawah _dianggap sebagai variabel " Saya tidak Peduli " atau " Throwaway " dalam Python

  • Penerjemah python menyimpan nilai ekspresi terakhir ke variabel khusus yang disebut _.

    >>> 10 
    10
    
    >>> _ 
    10
    
    >>> _ * 3 
    30
  • Garis bawah _juga digunakan untuk mengabaikan nilai spesifik. Jika Anda tidak membutuhkan nilai spesifik atau nilai tidak digunakan, tetapkan saja nilai tersebut dengan garis bawah.

    Abaikan nilai saat membuka kemasan

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

    Abaikan indeks

    for _ in range(10):     
        do_something()
Ashish Sahu
sumber
2
Ada penggunaan ketiga, yaitu untuk fungsi internasionalisasi _("Hello world!").
Jeff Younker
3
Pada level prosesor, apakah sebenarnya ada perbedaan antara "untuk _ dalam jangkauan" dan "untuk x dalam kisaran" dan kemudian tidak menggunakan x? Atau hanya untuk keterbacaan manusia?
iammax
1
@ iammax Menggunakan dismodul saya menemukan tidak ada perbedaan dalam bytecode. Namun, manfaat keterbacaan manusia jelas.
Alistair Carscadden
21

Ada 5 kasus untuk menggunakan garis bawah di Python.

  1. Untuk menyimpan nilai ekspresi terakhir dalam interpreter.

  2. Untuk mengabaikan nilai-nilai spesifik. (disebut "Saya tidak peduli")

  3. Untuk memberikan makna dan fungsi khusus untuk nama vartiables atau fungsi.

  4. Untuk digunakan sebagai fungsi 'Internasionalisasi (i18n)' atau 'Lokalisasi (l10n)'.

  5. Untuk memisahkan digit nilai angka literal.

Berikut adalah artikel yang bagus dengan contoh-contoh oleh mingrammer .

Diperhatikan
sumber
2
Sebenarnya itu blog.pythonlibrary.org
MichaelChirico
3

Sejauh menyangkut bahasa Python, _tidak memiliki arti khusus. Ini adalah pengidentifikasi yang valid seperti _foo, foo_atau _f_o_o_.

Arti khusus apa pun _adalah murni berdasarkan konvensi. Beberapa kasus umum:

  • Nama dummy saat variabel tidak dimaksudkan untuk digunakan, tetapi nama diperlukan oleh sintaks / semantik.

    # iteration disregarding content
    sum(1 for _ in some_iterable)
    # unpacking disregarding specific elements
    head, *_ = values
    # function disregarding its argument
    def callback(_): return True
  • Banyak REPLs / shells menyimpan hasil ekspresi tingkat atas terakhir builtins._.

    Identifier khusus _digunakan dalam interpreter interaktif untuk menyimpan hasil evaluasi terakhir; itu disimpan dalam builtinsmodul. Ketika tidak dalam mode interaktif, _tidak memiliki arti khusus dan tidak didefinisikan. [ sumber ]

    Karena cara nama-nama tersebut dilihat, kecuali dibayangi oleh _definisi global atau lokal yang _merujuk kepadanya 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

    Catatan: Beberapa shell seperti ipythontidak ditugaskan builtins._tapi case khusus _.

  • Dalam konteks internasionalisasi dan pelokalan, _digunakan sebagai alias untuk fungsi terjemahan utama.

    gettext.gettext (pesan)

    Kembalikan terjemahan pesan yang dilokalkan, berdasarkan pada domain global, bahasa, dan direktori lokal saat ini. Fungsi ini biasanya disebut sebagai _ () di namespace lokal (lihat contoh di bawah).

MisterMiyagi
sumber