Saya yakin ada cara sederhana untuk melakukan ini yang tidak terjadi pada saya.
Saya memanggil banyak metode yang mengembalikan daftar. Daftarnya mungkin kosong. Jika daftar ini tidak kosong, saya ingin mengembalikan item pertama; jika tidak, saya ingin mengembalikan None. Kode ini berfungsi:
my_list = get_list()
if len(my_list) > 0: return my_list[0]
return None
Tampaknya bagi saya harus ada idiom satu garis sederhana untuk melakukan ini, tetapi untuk kehidupan saya, saya tidak dapat memikirkannya. Disana?
Edit:
Alasan saya mencari ekspresi satu baris di sini bukan karena saya suka kode yang sangat singkat, tetapi karena saya harus menulis banyak kode seperti ini:
x = get_first_list()
if x:
# do something with x[0]
# inevitably forget the [0] part, and have a bug to fix
y = get_second_list()
if y:
# do something with y[0]
# inevitably forget the [0] part AGAIN, and have another bug to fix
Apa yang ingin saya lakukan tentu saja dapat dicapai dengan suatu fungsi (dan mungkin akan):
def first_item(list_or_none):
if list_or_none: return list_or_none[0]
x = first_item(get_first_list())
if x:
# do something with x
y = first_item(get_second_list())
if y:
# do something with y
Saya memposting pertanyaan karena saya sering terkejut dengan apa yang bisa dilakukan ekspresi sederhana dengan Python, dan saya pikir menulis fungsi adalah hal yang konyol untuk dilakukan jika ada ekspresi sederhana yang bisa melakukan trik. Tetapi melihat jawaban ini, sepertinya fungsi adalah solusi sederhana.
sumber
next(iter(your_list), None)
alih-alihfirst_item(your_list)
dengan asumsiyour_list
tidakNone
(get_first_list()
danget_second_list()
harus selalu mengembalikan iterable).next(iter(your_list))
, karena jika Anda memberikan argumen keduaiter
, Anda mengatakan bahwa argumen pertama dapat dipanggil.None
ini parameter kedua untuknext()
, bukaniter()
.next()
mengembalikan parameter kedua jika diberikan alih-alih menaikkanStopIteration
jikayour_list
kosong.Jawaban:
Python 2.6+
Jika
your_list
bisaNone
:Python 2.4
Contoh:
Pilihan lain adalah dengan menggarisbawahi fungsi di atas:
Untuk menghindari
break
Anda bisa menulis:Dimana:
sumber
""
dalam daftar, itu dibuang dan diganti dengan daftar kosong[]
. Jika Anda memiliki 0, juga diganti dengan[]
. Jika sudahFalse
ada di sana, ganti juga. Dll. Anda mungkin lolos dengan ini dalam kasus tertentu, tetapi ini adalah kebiasaan buruk untuk dikembangkan.bool(lst)
memberi tahu kami apakahlen(lst) > 0
item tersebut tidak memberi tahu kami tentang item apa yanglst
berisi mis.,bool([False]) == True;
oleh karena itu ekspresi[False] or []
kembali[False]
, hal yang sama juga terjadi untuk[0] or []
mengembalikannya[0]
.yield_first()
untuk menghindaribreak
pernyataan.Cara terbaik adalah ini:
Anda juga bisa melakukannya dalam satu baris, tetapi jauh lebih sulit bagi programmer untuk membaca:
sumber
next(iter(your_list), None)
next(iter(your_list))
sudah cukupNone
seperti yang diminta OP. Cobalah:next(iter([]))
.Itu seharusnya bekerja.
BTW Saya tidak menggunakan variabel
list
, karena itu menimpalist()
fungsi builtin .Sunting: Saya memiliki versi yang sedikit lebih sederhana, tetapi salah di sini sebelumnya.
sumber
Cara idiom paling python adalah dengan menggunakan next () pada iterator karena daftar iterable . seperti apa yang dimasukkan @JFSebastian dalam komentar pada 13 Des 2011.
next(iter(the_list), None)
Ini mengembalikan None jikathe_list
kosong. lihat selanjutnya () Python 2.6+atau jika Anda tahu pasti
the_list
tidak kosong:iter(the_list).next()
lihat iterator.next () Python 2.2+sumber
return l[0] if l else None
jika daftar tersebut adalah libcomp. Ketika daftar sebenarnya adalah genexpr, ini bahkan lebih baik karena Anda tidak harus membangun seluruh daftar seperti dinext(iter(x for x in range(10) if x % 2 == 0), None)
the_list
tidak kosong, Anda akan menulisthe_list[0]
.Jika Anda mencoba untuk memetik hal pertama (atau Tidak Ada) dari pemahaman daftar, Anda dapat beralih ke generator untuk melakukannya seperti:
Pro: berfungsi jika bla tidak dapat diindeks Con: itu sintaksis yang tidak dikenal. Ini berguna saat meretas dan memfilter hal-hal di ipython.
sumber
Solusi OP hampir tiba, hanya ada beberapa hal untuk membuatnya lebih Pythonic.
Untuk satu, tidak perlu mendapatkan panjang daftar. Daftar kosong di Python mengevaluasi ke False dalam tanda centang if. Cukup katakan
Selain itu, itu adalah ide yang sangat buruk untuk menetapkan variabel yang tumpang tindih dengan kata-kata yang dipesan. "daftar" adalah kata yang disediakan dalam Python.
Jadi mari kita ubah ke
Poin yang sangat penting yang terlewatkan oleh banyak solusi di sini adalah bahwa semua fungsi / metode Python mengembalikan None secara default . Coba yang berikut di bawah ini.
Jika Anda tidak perlu mengembalikan None untuk menghentikan fungsi lebih awal, Anda tidak perlu mengembalikannya secara eksplisit. Cukup ringkas, kembalikan saja entri pertama, jika ada.
Dan akhirnya, mungkin ini tersirat, tetapi hanya untuk menjadi eksplisit (karena eksplisit lebih baik daripada implisit ), Anda seharusnya tidak memiliki fungsi Anda mendapatkan daftar dari fungsi lain; cukup kirimkan sebagai parameter. Jadi, hasil akhirnya adalah
Seperti yang saya katakan, OP sudah hampir sampai, dan hanya beberapa sentuhan memberikan rasa Python yang Anda cari.
sumber
get_first_item
harus menerimadefault
parameter (sepertidict.get
) yang secara default menjadi Tidak ada. Dengan demikian antarmuka fungsi berkomunikasi secara eksplisit apa yang terjadi jikamy_list
kosong.sumber
Terus terang, saya tidak berpikir ada idiom yang lebih baik: Anda jelas dan singkat - tidak perlu untuk sesuatu yang "lebih baik". Mungkin, tetapi ini benar-benar masalah selera, Anda dapat mengubahnya
if len(list) > 0:
denganif list:
- daftar kosong akan selalu mengevaluasi ke False.Pada catatan terkait, Python bukan Perl (tidak ada permainan kata-kata!), Anda tidak perlu mendapatkan kode paling keren.
Sebenarnya, kode terburuk yang saya lihat di Python, juga sangat keren :-) dan benar-benar tidak dapat dipelihara.
Ngomong-ngomong, sebagian besar solusi yang saya lihat di sini tidak mempertimbangkan ketika daftar [0] dievaluasi menjadi False (mis. String kosong, atau nol) - dalam hal ini, mereka semua mengembalikan Tidak ada dan bukan elemen yang benar.
sumber
if lst:
daripadaif len(lst) > 0:
. Juga, jangan gunakan kata kunci Python sebagai nama variabel; itu berakhir dengan air mata. Biasa digunakanL
ataulst
sebagai nama variabel untuk beberapa daftar. Saya yakin dalam hal ini Anda tidak bermaksud menyarankan untuk menggunakanlist
sebagai nama variabel, Anda hanya bermaksud "daftar". Dan, +1 untuk "saat pertama [0] dievaluasi menjadi Salah".Pendekatan paling Pythonic adalah apa yang ditunjukkan oleh jawaban yang paling banyak dipilih, dan itu adalah hal pertama yang muncul di benak saya ketika saya membaca pertanyaan itu. Berikut cara menggunakannya, pertama-tama jika daftar yang kosong dilewatkan ke fungsi:
Dan jika daftar dikembalikan dari suatu
get_list
fungsi:Cara lain ditunjukkan untuk melakukan ini di sini, dengan penjelasan
for
Ketika saya mulai mencoba memikirkan cara cerdas untuk melakukan ini, ini adalah hal kedua yang saya pikirkan:
Ini menganggap fungsi berakhir di sini, secara implisit mengembalikan
None
jikaget_list
mengembalikan daftar kosong. Kode eksplisit di bawah ini persis sama:if some_list
Berikut ini juga diusulkan (saya memperbaiki nama variabel yang salah) yang juga menggunakan implisit
None
. Ini lebih disukai daripada yang di atas, karena menggunakan pemeriksaan logis alih-alih iterasi yang mungkin tidak terjadi. Ini harus lebih mudah untuk segera memahami apa yang terjadi. Tetapi jika kita menulis untuk keterbacaan dan pemeliharaan, kita juga harus menambahkan eksplisitreturn None
di akhir:iris
or [None]
dan pilih indeks nolJawaban ini juga dalam jawaban yang paling banyak dipilih:
Iris tidak perlu, dan membuat daftar satu item tambahan dalam memori. Yang berikut harus lebih performan. Untuk menjelaskan,
or
mengembalikan elemen kedua jika yang pertamaFalse
dalam konteks boolean, jadi jikaget_list
mengembalikan daftar kosong, ekspresi yang terkandung dalam tanda kurung akan mengembalikan daftar dengan 'Tidak Ada', yang kemudian akan diakses oleh0
indeks:Yang berikutnya menggunakan fakta itu dan mengembalikan item kedua jika yang pertama
True
dalam konteks boolean, dan karena mereferensikan my_list dua kali, itu tidak lebih baik daripada ekspresi ternary (dan secara teknis bukan satu-liner):next
Kemudian kita memiliki penggunaan pintar dari builtin
next
daniter
Untuk menjelaskan,
iter
kembalikan iterator dengan.next
metode. (.__next__
dalam Python 3.) Kemudian builtinnext
memanggil.next
metode itu, dan jika iterator habis, mengembalikan default yang kita berikanNone
,.ekspresi ternary berlebihan (
a if b else c
) dan berputar-putar kembaliDi bawah ini diusulkan, tetapi kebalikannya akan lebih disukai, karena logika biasanya lebih baik dipahami dalam hal positif daripada negatif. Karena
get_list
dipanggil dua kali, kecuali jika hasilnya memoise dalam beberapa cara, ini akan berkinerja buruk:Pembalikan yang lebih baik:
Lebih baik lagi, gunakan variabel lokal sehingga
get_list
hanya disebut satu kali, dan Anda memiliki solusi Pythonic yang direkomendasikan pertama kali dibahas:sumber
Mengenai idiom, ada resep itertools yang disebut
nth
.Dari resep itertools:
Jika Anda ingin one-liners, pertimbangkan untuk menginstal perpustakaan yang mengimplementasikan resep ini untuk Anda, misalnya
more_itertools
:Alat lain tersedia yang hanya mengembalikan item pertama, yang disebut
more_itertools.first
.Itertools ini secara umum skala untuk setiap iterable, tidak hanya untuk daftar.
sumber
my_list[0] if len(my_list) else None
sumber
len
tanpa alasan. Jika Anda menghapusnya, kode di atas akan melakukan hal yang sama.Karena penasaran, saya menjalankan timing pada dua solusi. Solusi yang menggunakan pernyataan kembali untuk mengakhiri sebelum untuk loop sedikit lebih mahal pada mesin saya dengan Python 2.5.1, saya menduga ini ada hubungannya dengan pengaturan iterable.
Ini adalah timing yang saya dapat:
sumber
sumber
if len(a) > 0:
tetapi ini dianggap gaya yang baik. Perhatikan seberapa baik ini mengekspresikan masalah: "cobalah untuk mengekstrak kepala daftar, dan jika itu tidak berhasil, kembaliNone
". Pencarian Google untuk "EAFP" atau lihat di sini: python.net/~goodger/projects/pycon/2007/idiomatic/…BTW: Saya akan mengerjakan ulang aliran program umum Anda menjadi sesuatu seperti ini:
(Menghindari pengulangan bila memungkinkan)
sumber
Bagaimana dengan ini:
(my_list and my_list[0]) or None
Catatan: Ini harus berfungsi dengan baik untuk daftar objek tetapi mungkin mengembalikan jawaban yang salah jika jumlah atau daftar string per komentar di bawah ini.
sumber
([0,1] and 0) or None
!(['','A'] and '') or None
.my_list[0]
dievaluasi sebagaiFalse
, hasilnya harusNone
.my_list[0] if len(my_list) else None
Tidak yakin bagaimana pythonic ini tetapi sampai ada fungsi pertama di perpustakaan saya memasukkan ini dalam sumber:
Ini hanya satu baris (sesuai dengan hitam) dan menghindari ketergantungan.
sumber
Menggunakan dan-atau trik:
sumber
Mungkin bukan solusi tercepat, tetapi tidak ada yang menyebutkan opsi ini:
jika
get_list()
dapat kembali,None
Anda dapat menggunakan:Keuntungan:
-satu baris
-Anda hanya menelepon
get_list()
sekali-mudah dimengerti
sumber
Kasus penggunaan saya hanya untuk mengatur nilai variabel lokal.
Secara pribadi saya menemukan mencoba dan kecuali pembersih gaya untuk membaca
daripada mengiris daftar.
sumber
Beberapa orang menyarankan melakukan sesuatu seperti ini:
Itu berfungsi dalam banyak kasus, tetapi hanya akan berfungsi jika daftar [0] tidak sama dengan 0, False, atau string kosong. Jika daftar [0] adalah 0, Salah, atau string kosong, metode ini tidak akan mengembalikan satupun.
sumber
Anda dapat menggunakan Metode Ekstrak . Dengan kata lain, ekstrak kode itu ke metode yang akan Anda panggil.
Saya tidak akan mencoba untuk mengompresnya lebih banyak, satu baris sepertinya lebih sulit dibaca daripada versi verbose. Dan jika Anda menggunakan Metode Ekstrak, itu adalah satu liner;)
sumber
sumber
bukan python idiomatik yang setara dengan operator ternary C-style
yaitu.
sumber