Pertanyaan Bagaimana cara memeriksa apakah daftar kosong?


Misalnya, jika melewati yang berikut:

a = []

Bagaimana cara memeriksa untuk melihat apakah a kosong?


2718
2017-09-10 06:20


asal


Jawaban:


if not a:
  print("List is empty")

Menggunakan booleanness implisit dari daftar kosong cukup pythonic.


3886
2017-09-10 06:28



Cara pythonic untuk melakukannya adalah dari Panduan gaya PEP 8 (dimana iya nih berarti "direkomendasikan" dan Tidak berarti "tidak direkomendasikan"):

Untuk urutan, (string, daftar, tupel), gunakan fakta bahwa urutan kosong adalah salah.   

Iya nih: if not seq:
     if seq:

Tidak:  if len(seq):
     if not len(seq):

862
2017-09-10 10:33



Saya lebih suka secara eksplisit:

if len(li) == 0:
    print('the list is empty')

Cara ini 100% jelas itu li adalah urutan (daftar) dan kami ingin menguji ukurannya. Masalah saya dengan if not li: ... adalah bahwa itu memberikan kesan yang salah itu li adalah variabel boolean.


517
2017-09-05 00:30



Orang lain tampaknya menggeneralisasi pertanyaan di luar daftar, jadi saya pikir saya akan menambahkan peringatan untuk jenis urutan yang berbeda yang mungkin digunakan banyak orang, terutama karena ini adalah klik google pertama untuk "uji python array kosong" .

Metode lain tidak berfungsi untuk array numpy

Anda harus berhati-hati dengan array numpy, karena metode lain yang berfungsi dengan baik lists atau kontainer standar lainnya gagal untuk array numpy. Saya menjelaskan mengapa di bawah ini, tetapi singkatnya, metode yang disukai adalah untuk digunakan size.

Cara "pythonic" tidak berfungsi: Bagian 1

The "pythonic" gagal dengan cara numpy array karena numpy mencoba untuk melemparkan array ke array bools, dan if x mencoba untuk mengevaluasi semua itu bools sekaligus untuk beberapa jenis nilai kebenaran agregat. Tapi ini tidak masuk akal, jadi Anda mendapatkan ValueError:

>>> x = numpy.array([0,1])
>>> if x: print("x")
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Cara "pythonic" tidak berfungsi: Bagian 2

Tapi setidaknya kasus di atas memberi tahu Anda bahwa itu gagal. Jika Anda memiliki array numpy dengan satu elemen, maka if Pernyataan akan "berfungsi", dalam arti Anda tidak mendapatkan kesalahan. Namun, jika satu elemen itu terjadi 0 (atau 0.0, atau false, ...), yang if pernyataan akan salah hasil false:

>>> x = numpy.array([0,])
>>> if x: print("x")
... else: print("No x")
No x

Tapi yang jelas x ada dan tidak kosong! Hasil ini bukan yang Anda inginkan.

Menggunakan len dapat memberikan hasil yang tidak diharapkan

Sebagai contoh,

len( numpy.zeros((1,0)) )

mengembalikan 1, meskipun array memiliki elemen nol.

Cara numpythonic

Sebagaimana dijelaskan dalam FAQ scipyMetode yang benar dalam semua kasus di mana Anda tahu Anda memiliki array numpy adalah untuk digunakan if x.size:

>>> x = numpy.array([0,1])
>>> if x.size: print("x")
x

>>> x = numpy.array([0,])
>>> if x.size: print("x")
... else: print("No x")
x

>>> x = numpy.zeros((1,0))
>>> if x.size: print("x")
... else: print("No x")
No x

Jika Anda tidak yakin apakah itu mungkin list, array numpy, atau sesuatu yang lain, Anda bisa menggabungkan pendekatan ini dengan jawabannya @dubiousjim memberi untuk memastikan tes yang tepat digunakan untuk setiap jenis. Tidak terlalu "pythonic", tetapi ternyata bahwa numpy sengaja mematahkan pythonicity setidaknya dalam pengertian ini.

Jika Anda perlu melakukan lebih dari sekedar memeriksa apakah input kosong, dan Anda menggunakan fitur numpy lain seperti pengindeksan atau operasi matematika, itu mungkin lebih efisien (dan tentu saja lebih umum) untuk memaksa input menjadi array numpy. Ada beberapa fungsi bagus untuk melakukan ini dengan cepat - yang paling penting numpy.asarray. Ini mengambil masukan Anda, tidak melakukan apa-apa jika itu sudah menjadi larik, atau membungkus masukan Anda ke dalam larik jika itu adalah daftar, tupel, dll., Dan secara opsional mengonversinya ke yang Anda pilih dtype. Jadi sangat cepat kapan pun bisa, dan itu memastikan bahwa Anda hanya bisa menganggap input adalah array numpy. Kami biasanya bahkan hanya menggunakan nama yang sama, karena konversi ke array tidak akan membuatnya kembali di luar arus cakupan:

x = numpy.asarray(x, dtype=numpy.double)

Ini akan membuat x.size periksa pekerjaan dalam semua kasus yang saya lihat di halaman ini.


208
2018-02-21 16:48



Daftar kosong itu sendiri dianggap salah dalam pengujian nilai nyata (lihat dokumentasi python):

a = []
if a:
     print "not empty"

@Daren Thomas

EDIT: Titik lain terhadap pengujian   daftar kosong sebagai False: Bagaimana dengan   polimorfisme? Anda tidak harus bergantung pada   daftar menjadi daftar. Itu seharusnya   kwek seperti bebek - bagaimana kabarmu?   untuk mendapatkan duckCollection Anda ke quack   'Salah' ketika tidak memiliki elemen?

DuckCollection Anda harus diterapkan __nonzero__ atau __len__ jadi jika a: akan bekerja tanpa masalah.


103
2017-09-10 06:31



Jawaban Patrick (diterima) benar: if not a: adalah cara yang tepat untuk melakukannya. Jawaban Harley Holcombe benar bahwa ini ada di panduan gaya PEP 8. Tetapi apa yang tidak dijawab oleh semua jawaban adalah mengapa itu ide yang bagus untuk mengikuti idiom — bahkan jika Anda secara pribadi merasa itu tidak cukup eksplisit atau membingungkan bagi pengguna Ruby atau apa pun.

Kode Python, dan komunitas Python, memiliki idiom yang sangat kuat. Mengikuti idiom tersebut membuat kode Anda lebih mudah dibaca bagi siapa pun yang berpengalaman dengan Python. Dan ketika Anda melanggar idiom itu, itu adalah sinyal yang kuat.

Memang benar itu if not a: tidak membedakan daftar kosong dari None, atau numerik 0, atau tupel kosong, atau jenis pengumpulan pengguna yang dibuat kosong, atau jenis kumpulan tidak-cukup-yang dibuat pengguna kosong, atau elemen tunggal NumPy array yang bertindak sebagai skalar dengan nilai palsu, dll. Dan kadang-kadang penting untuk eksplisit tentang itu. Dan dalam hal itu, Anda tahu apa Anda ingin bersikap eksplisit tentang, sehingga Anda dapat menguji hal itu. Sebagai contoh, if not a and a is not None: berarti "apapun yang falsey kecuali None", sementara if len(a) != 0: berarti "hanya urutan kosong - dan apa pun selain urutan adalah kesalahan di sini", dan seterusnya. Selain menguji apa yang ingin Anda uji, ini juga memberi sinyal kepada pembaca bahwa tes ini penting.

Tetapi ketika Anda tidak memiliki sesuatu untuk menjadi eksplisit, apa pun selain if not a: menyesatkan pembaca. Anda menandakan sesuatu yang penting saat tidak. (Anda mungkin juga membuat kode kurang fleksibel, atau lebih lambat, atau apa pun, tetapi itu semua kurang penting.) Dan jika Anda biasanya menyesatkan pembaca seperti ini, lalu ketika Anda melakukan perlu membuat perbedaan, itu akan berlalu tanpa disadari karena Anda telah "menangis serigala" di seluruh kode Anda.


81
2017-12-03 02:21



Cara terbaik untuk memeriksa apakah daftar kosong

Misalnya, jika melewati yang berikut:

a = []

Bagaimana saya memeriksa untuk melihat apakah kosong?

Jawaban singkat:

Tempatkan daftar dalam konteks boolean (misalnya, dengan if atau whilepernyataan). Ini akan menguji False jika kosong, dan True jika tidak. Sebagai contoh:

if not a:                           # do this!
    print('a is an empty list')

Naik banding ke Otoritas

PEP 8, panduan gaya Python resmi untuk kode Python di pustaka standar Python, menegaskan:

Untuk urutan, (string, daftar, tupel), gunakan fakta bahwa urutan kosong adalah salah.

Yes: if not seq:
     if seq:

No: if len(seq):
    if not len(seq):

Kita harus berharap bahwa kode perpustakaan standar harus berfungsi dan benar mungkin. Tetapi mengapa demikian halnya, dan mengapa kita membutuhkan panduan ini?

Penjelasan

Saya sering melihat kode seperti ini dari programmer berpengalaman baru ke Python:

if len(a) == 0:                     # Don't do this!
    print('a is an empty list')

Dan pengguna bahasa malas mungkin tergoda untuk melakukan ini:

if a == []:                         # Don't do this!
    print('a is an empty list')

Ini benar dalam bahasa lain masing-masing. Dan ini bahkan semantis benar dengan Python.

Namun kami menganggapnya tidak-Pythonic karena Python mendukung semantik ini secara langsung di antarmuka objek daftar melalui pemaksaan boolean.

Dari dokumen (dan perhatikan secara khusus dimasukkannya daftar kosong, []):

Secara default, sebuah objek dianggap benar kecuali kelasnya mendefinisikan   baik a __bool__() metode yang mengembalikan False atau a __len__() metode   yang mengembalikan nol, saat dipanggil dengan objek. Di sini sebagian besar objek bawaan dianggap salah:

  • konstanta yang didefinisikan salah: None dan False.
  • nol dari jenis angka apa pun: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
  • urutan dan koleksi kosong: '', (), [], {}, set(), range(0)

Dan dokumentasi datamodel:

object.__bool__(self)

Dipanggil untuk menerapkan pengujian nilai kebenaran dan operasi yang sudah ada bool(); harus kembali False atau True. Ketika metode ini tidak ditentukan,    __len__() disebut, jika didefinisikan, dan objek dianggap benar jika hasilnya tidak nol. Jika kelas tidak mendefinisikan keduanya __len__()   maupun __bool__(), semua contohnya dianggap benar.

dan

object.__len__(self)

Dipanggil untuk mengimplementasikan fungsi bawaan len(). Harus mengembalikan panjang objek, bilangan bulat> = 0. Juga, objek yang tidak menentukan a __bool__() metode dan siapa __len__() metode mengembalikan nol dianggap salah dalam konteks Boolean.

Jadi, bukannya ini:

if len(a) == 0:                     # Don't do this!
    print('a is an empty list')

atau ini:

if a == []:                     # Don't do this!
    print('a is an empty list')

Melakukan hal ini:

if not a:
    print('a is an empty list')

Melakukan apa yang Pythonic biasanya terbayar dalam kinerja:

Apakah itu berhasil? (Perhatikan bahwa lebih sedikit waktu untuk melakukan operasi yang setara lebih baik :)

>>> import timeit
>>> min(timeit.repeat(lambda: len([]) == 0, repeat=100))
0.13775854044661884
>>> min(timeit.repeat(lambda: [] == [], repeat=100))
0.0984637276455409
>>> min(timeit.repeat(lambda: not [], repeat=100))
0.07878462291455435

Untuk skala, inilah biaya untuk memanggil fungsi dan membangun dan mengembalikan daftar kosong, yang dapat Anda kurangi dari biaya cek kekosongan yang digunakan di atas:

>>> min(timeit.repeat(lambda: [], repeat=100))
0.07074015751817342

Kami melihatnya antara memeriksa panjang dengan fungsi builtin len dibandingkan dengan 0  atau memeriksa daftar kosong banyak kurang berkinerja daripada menggunakan sintaks builtin bahasa seperti yang didokumentasikan.

Mengapa?

Untuk len(a) == 0 memeriksa:

Pertama Python harus memeriksa global untuk melihat apakah len dibayangi.

Maka harus memanggil fungsi, memuat 0, dan lakukan perbandingan kesetaraan dengan Python (bukan dengan C):

>>> import dis
>>> dis.dis(lambda: len([]) == 0)
  1           0 LOAD_GLOBAL              0 (len)
              2 BUILD_LIST               0
              4 CALL_FUNCTION            1
              6 LOAD_CONST               1 (0)
              8 COMPARE_OP               2 (==)
             10 RETURN_VALUE

Dan untuk [] == []ia harus membuat daftar yang tidak perlu dan kemudian, sekali lagi, melakukan operasi perbandingan dalam mesin virtual Python (dibandingkan dengan C)

>>> dis.dis(lambda: [] == [])
  1           0 BUILD_LIST               0
              2 BUILD_LIST               0
              4 COMPARE_OP               2 (==)
              6 RETURN_VALUE

Cara "Pythonic" adalah pemeriksaan yang jauh lebih sederhana dan lebih cepat karena panjang daftar di-cache dalam header contoh objek:

>>> dis.dis(lambda: not [])
  1           0 BUILD_LIST               0
              2 UNARY_NOT
              4 RETURN_VALUE

Bukti dari sumber C dan dokumentasi

PyVarObject

Ini merupakan perpanjangan dari PyObject yang menambahkan ob_size bidang. Ini hanya digunakan untuk objek yang memiliki beberapa pengertian panjang. Jenis ini tidak sering muncul di Python / C API. Ini sesuai dengan bidang yang ditentukan oleh perluasan PyObject_VAR_HEAD makro.

Dari sumber c di Sertakan / listobject.h:

typedef struct {
    PyObject_VAR_HEAD
    /* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
    PyObject **ob_item;

    /* ob_item contains space for 'allocated' elements.  The number
     * currently in use is ob_size.
     * Invariants:
     *     0 <= ob_size <= allocated
     *     len(list) == ob_size

Saya telah menikmati penelitian ini dan saya menghabiskan banyak waktu untuk mengkaji jawaban saya. Jika Anda berpikir saya meninggalkan sesuatu, tolong beri tahu saya dalam komentar.


80
2017-08-20 03:50



Saya telah melihat yang di bawah ini sebagai pilihan:

if not a:
    print("The list is empty or null")

62
2017-09-10 06:28



Mengapa harus memeriksanya?

Sepertinya tidak ada yang menjawab pertanyaan Anda perlu untuk menguji daftar di tempat pertama. Karena Anda tidak memberikan konteks tambahan, saya dapat membayangkan bahwa Anda mungkin tidak perlu melakukan pemeriksaan ini di tempat pertama, tetapi tidak terbiasa dengan pemrosesan daftar dengan Python.

Saya berpendapat bahwa kebanyakan pythonic caranya adalah dengan tidak memeriksa sama sekali, melainkan hanya memproses daftar. Dengan begitu ia akan melakukan hal yang benar, entah kosong atau penuh.

a = []

for item in a:
    <do something with item>

<rest of code>

Ini memiliki manfaat menangani konten apa pun Sebuah, sementara tidak membutuhkan pemeriksaan khusus untuk kekosongan. Jika Sebuah kosong, blok dependen tidak akan dieksekusi dan interpreter akan jatuh ke baris berikutnya.

Jika Anda benar-benar perlu memeriksa array untuk kekosongan, jawaban yang lain sudah cukup.


50
2017-10-06 19:25



len() adalah operasi O (1) untuk daftar Python, string, dicts, dan set. Python secara internal melacak jumlah elemen dalam wadah ini.

JavaScript memiliki gagasan yang sama tentang kebenaran / kesalahan.


44
2017-09-15 05:50



Saya telah menulis:

if isinstance(a, (list, some, other, types, i, accept)) and not a:
    do_stuff

yang terpilih -1. Saya tidak yakin kalau itu karena pembaca keberatan dengan strategi atau berpikir jawabannya tidak membantu seperti yang disajikan. Saya akan berpura-pura itu yang terakhir, karena --- apa pun dianggap sebagai "pythonic" --- ini adalah strategi yang benar. Kecuali Anda sudah mengesampingkan, atau siap menangani kasus di mana a adalah, misalnya, False, Anda perlu tes yang lebih ketat daripada hanya if not a:. Anda bisa menggunakan sesuatu seperti ini:

if isinstance(a, numpy.ndarray) and not a.size:
    do_stuff
elif isinstance(a, collections.Sized) and not a:
    do_stuff

tes pertama adalah jawaban atas jawaban @ Mike, di atas. Baris ketiga juga bisa diganti dengan:

elif isinstance(a, (list, tuple)) and not a:

jika Anda hanya ingin menerima contoh jenis tertentu (dan subtipe mereka), atau dengan:

elif isinstance(a, (list, tuple)) and not len(a):

Anda bisa lolos tanpa pemeriksaan tipe eksplisit, tetapi hanya jika konteks di sekitarnya sudah meyakinkan Anda itu a adalah nilai dari jenis yang Anda siap atasi, atau jika Anda yakin bahwa jenis yang tidak siap ditangani akan meningkatkan kesalahan (mis., TypeError jika kamu menelepon len pada nilai yang tidak terdefinisi) yang siap Anda tangani. Secara umum, konvensi "pythonic" tampaknya berjalan dengan cara terakhir ini. Remas seperti bebek dan biarkan ia menaikan DuckError jika ia tidak tahu cara membuat dukun. Anda masih harus melakukannya berpikir tentang asumsi jenis apa yang Anda buat, dan apakah kasus yang tidak siap ditangani dengan benar benar-benar akan salah di tempat yang tepat. Array Numpy adalah contoh yang baik di mana hanya mengandalkan secara membabi buta len atau typecast boolean mungkin tidak tepat seperti yang Anda harapkan.


28
2018-05-31 14:35