Bir listenin boş olup olmadığını nasıl kontrol ederim?


3234

Örneğin, aşağıdakileri geçtiyse:

a = []

aBoş olup olmadığını nasıl kontrol ederim ?

Yanıtlar:


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

Kullanılması örtük booleanness boş ait listoldukça pythonic olduğunu.


1130
Şeytanın avukatı oynuyor. Bu deyimin neden pitonik olduğunu anlamıyorum. 'Açık, örtükten daha iyidir', değil mi? Bu kontrol neyin kontrol edildiğiyle ilgili çok açık görünmüyor.
James McMahon

222
@JamesMcMahon - açıklık ve tür esnekliği arasında bir denge. genel olarak "açık olmak", "büyülü" şeyler yapmamak anlamına gelir. Öte yandan, "ördek yazma", türleri açıkça kontrol etmek yerine, daha genel arayüzlerle çalışmak anlamına gelir. şey şöyle if a == []özgün bir tip (zorluyor () == []olan False). burada genel fikir birliği, ördek yazmanın kazanacağı gibi görünüyor (aslında, __nonzero__boşluğu test etmek için bir arayüz olduğunu söyleyerek docs.python.org/reference/datamodel.html#object.__nonzero__ )
Andrew

38
Bu yöntem numpy dizileri üzerinde çalışmaz .. bu yüzden len (a) == 0 hem "ördek yazarak" hem de örtüklük açısından tercih edilebilir olduğunu düşünüyorum.
Mr.WorshipMe

10
C'deki bir dizinin boş olup olmadığını anlamanın kanonik yolu, ilk öğenin kaydını silip null olup olmadığını görmek, boş sonlandırılmış bir dizi olduğunu varsayarak. Aksi takdirde, dizi önemli bir boyuta sahipse, uzunluğunu sıfıra karşılaştırmak tamamen verimsizdir. Ayrıca, tipik olarak, boş bir dizi için bellek ayırmazsınız (işaretçi boş kalır), bu nedenle uzunluğunu almaya çalışmak mantıklı değildir. Ben len (a) == 0 bunu yapmak için iyi bir yol değil, sadece gördüğüm zaman bana 'C' bağırmaz demiyorum.
sleblanc

6
@BrennenSprimont, Boş sonlandırılmadıysa, uzunluğu ayrı bir değişkende saklanıyor mu yoksa diziniz uzunluğu izleyen bir kapta mı sarılmış olduğunu zaten biliyorsunuzdur. C ++, Java, C # bu tür kaplara sahiptir ve bazı "uzunluk" yöntemini etkin bir şekilde uygular. C'nin böyle bir şeyi yok , kendiniz yuvarlamanız gerekiyor. Statik olarak atanan C dizileri, yalnızca istediğiniz veri miktarını depolamak için yeterli alana sahip olduğu garanti edilen bir bellek alanına işaretçilerdir. C'de yerleşik olarak, o alanı ne kadar doldurduğunuzu bildirecek hiçbir şey yoktur.
sleblanc

1159

Bunu yapmanın pythonic yolu PEP 8 stil rehberinden (burada Evet “tavsiye edilir” ve Hayır “tavsiye edilmez” anlamına gelir):

Diziler (dizeler, listeler, tuples) için boş dizilerin yanlış olduğu gerçeğini kullanın.

Yes: if not seq:
     if seq:

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

49
Eğer seqliste benzeri bir nesne olması beklenen sinyal istiyorsanız ikinci yolu daha iyi görünüyor .
BallpointBen

5
Pythonism savunucularının söyleyeceği @BallpointBen, değişkenin adlandırıldığı şekilde örtük olmalıdır
axolotl

9
@BallpointBen, bir değişkenin ne olması gerektiğini bildirmek için Python'un tür ipuçlarını kullanmayı deneyin . 3.5 yılında tanıtıldı.
Boris

8
numpy bu deyimi kırdı ... seq = numpy.array ([1,2,3]) ardından seq bir istisna oluşturuyorsa "ValueError: Birden fazla öğeye sahip bir dizinin gerçek değeri belirsiz. a.any kullanın () veya a.all () "
Mr.WorshipMe

2
@jeronimo: Bunun lxml'e özgü bir uyarı olduğuna inanıyorum.
Harley Holcombe

767

Açıkça tercih ederim:

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

Bu şekilde libir sekans (liste) olan% 100 açıktır ve boyutunu test etmek istiyoruz. Benim sorunum boolean değişkeni if not li: ...olan yanlış izlenim vermek olmasıdır li.


91
Bir listenin uzunluğunun sıfıra eşit olup olmadığını kontrol etmek, sadece listenin yanlış olup olmadığını kontrol etmek, çirkin ve tek sesli. Python'a aşina olan hiç kimse libir bool olduğunu düşünmeyecek ve umursamayacaktır. Önemliyse, daha fazla kod değil, bir yorum eklemelisiniz.
Carl Smith

21
Bu, genellikle daha yavaş ve her zaman daha az okunabilir IMHO olan gereksiz bir kesin test gibi görünüyor. Boş bir şeyin boyutunu kontrol etmek yerine, neden sadece boş olup olmadığını kontrol etmiyorsunuz?
John B

34
Neyse, neden bu kötü (ve Python gibi güçlü deyimler ile bir dilde deyimler ihlal Genelde kötü olduğunu) istediğiniz, bunun nedeni özel olarak örneğin nedense (uzunluğunu kontrol ettiğiniz anlamına okuyucuya sinyalleri olmasıdır Noneya 0geçmektense istisna oluşturmak). Eğer var sebepsiz, için bunu yapmak zaman, yanıltıcı-ve aynı zamanda kod zaman anlamına gelir yapar ayrım yapma ihtiyacını da tüm kaynağın geri kalanı üzerinde "yersiz kurt" ettik, çünkü ayrım görünmez.
abarnert

18
Bu sadece gereksiz yere kodu uzatmak olduğunu düşünüyorum. Aksi halde, neden daha "açık" olmasın if bool(len(li) == 0) is True:?
augurar

11
@ Jabba , birçok durumda (yerleşik veri türleriyle çalıştığınız ) O (1) olacaktır , ancak buna güvenemezsiniz. Bu özelliğe sahip olmayan özel bir veri türüyle çalışıyor olabilirsiniz. Bu kodu yazdıktan sonra bu özel veri türünü daha sonra eklemeye de karar verebilirsiniz.
ralokt

324

Bu, "python testi boş dizi" ve benzer sorgular için ilk google hit, artı diğer insanlar soruyu sadece listelerin ötesinde genelleştiriyor gibi görünüyor, bu yüzden birçok insanın farklı bir dizi türü için bir uyarı ekleyeceğini düşündüm kullanabilir.

Diğer yöntemler NumPy dizileri için çalışmaz

NumPy dizilerine dikkat etmeniz gerekir, çünkü lists veya diğer standart kaplar için iyi çalışan diğer yöntemler NumPy dizileri için başarısız olur. Neden aşağıda izah ama kısacası tercih edilen yöntem kullanılmak etmektirsize .

"Pitonik" yol çalışmıyor: Bölüm 1

"Pythonic" yolu NumPy dizileriyle başarısız olur, çünkü NumPy diziyi bir bools dizisine yayınlamaya çalışır ve if xbu bools'nin tümünü bir kerede toplam doğruluk değeri için değerlendirmeye çalışır . Ama bu hiç mantıklı değil, yani 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()

"Pitonik" yol çalışmıyor: Bölüm 2

Ama en azından yukarıdaki durum bunun başarısız olduğunu söylüyor. Tam olarak bir öğeye sahip bir NumPy diziniz varsa, hata almamanız açısından ififade "çalışır". Ancak, bu bir öğe 0(veya 0.0, veya False...) ifolursa , ifade yanlış sonuç verir False:

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

Ama açıkça xvar ve boş değil! Bu sonuç istediğin gibi değil.

kullanma len beklenmedik sonuçlar verebilir

Örneğin,

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

Dizi sıfır öğeye sahip olmasına rağmen 1 değerini döndürür.

Numpythonic yolu

SciPy SSS bölümünde açıklandığı gibi, NumPy dizisine sahip olduğunuzu bildiğiniz tüm durumlarda doğru yöntem kullanmaktır 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

Bunun listbir NumPy dizisi veya başka bir şey olup olmadığından emin değilseniz, bu yaklaşımı @dubiousjim'in verdiği yanıtla birleştirebilirsiniz. her tür için doğru testin kullanıldığından emin olmak için . Çok "pitonik" değil, ama NumPy'nin en azından bu anlamda pythonicity'yi kasıtlı olduğu ortaya çıktı.

Girişin boş olup olmadığını kontrol etmekten daha fazlasını yapmanız gerekiyorsa ve indeksleme veya matematik işlemleri gibi diğer NumPy özelliklerini kullanıyorsanız, girişi bir NumPy dizisi olmaya zorlamak muhtemelen daha etkilidir (ve kesinlikle daha yaygındır) . Bunu hızlı bir şekilde yapmak için birkaç güzel işlev var - en önemlisi numpy.asarray. Bu, girdinizi alır, zaten bir dizi ise hiçbir şey yapmaz ya da bir liste, grup vb. İse girdinizi bir diziye sarar ve isteğe bağlı olarak seçtiğinize dönüştürür dtype. Bu yüzden olabildiğince hızlıdır ve girişin bir NumPy dizisi olduğunu varsaymanızı sağlar. Bir diziye dönüştürme işlemi geçerli kapsamın dışına çıkmayacağından, genellikle aynı adı kullanırız :

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

Bu x.size, bu sayfada gördüğüm tüm durumlarda çekin çalışmasını sağlayacaktır .


62
Bunun Python'da bir kusur olmadığını, aksine kasıtlı bir sözleşme kırılmasının numpy- numpyçok özel bir kullanım örneğine sahip bir kütüphane olduğunu ve bir dizideki gerçekliğin ne olduğuna dair farklı bir 'doğal' tanımına sahip olduğunu belirtmek gerekir. Konteynerler için Python standardı. Bu şekilde, bu durum için optimize etmek mantıklı olduğunu pathlibkullanımları /yerine concatenate yollarına +- bu standart dışı, ama bağlamda mantıklı.
Gareth Latty

9
Kabul. Benim demek o numpy ikisi için çok yaygın ördek yazarak kırmaya seçim yapmış hatırlamak önemlidir bu sadece bir if xve len(x)ve kırılması algılamak ve ayıklamak için çok zor olabilir bazen - deyimleri.
Mike

22
Bilmiyorum, benim için, len (x) adlı bir yöntem varsayımlar nedeniyle dizi uzunluğunu döndürmezse, adı kötü tasarlanmış.
Dalton

11
Bu sorunun numpy dizileri ile ilgisi yoktur
pppery

19
@ppperry Evet, asıl soru Numpy dizileriyle ilgili değildi, ama bunlarla ve muhtemelen ördek türü argümanlarla çalışırken, bu soru çok alakalı hale geliyor.
peterhil

223

Bir listenin boş olup olmadığını kontrol etmenin en iyi yolu

Örneğin, aşağıdakileri geçtiyse:

a = []

A'nın boş olup olmadığını nasıl kontrol ederim?

Kısa cevap:

Listeyi bir boole bağlamına yerleştirin (örneğin, ifveya whileifadesiyle). FalseBoş olup olmadığını test eder, Trueaksi takdirde. Örneğin:

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

PEP 8

Python'un standart kütüphanesindeki Python kodu için resmi Python stil rehberi PEP 8 şunları söylüyor:

Diziler (dizeler, listeler, tuples) için boş dizilerin yanlış olduğu gerçeğini kullanın.

Yes: if not seq:
     if seq:

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

Standart kütüphane kodunun olabildiğince performanslı ve doğru olmasını beklemeliyiz. Peki neden böyle ve neden bu rehberliğe ihtiyacımız var?

açıklama

Sık sık Python için yeni deneyimli programcılar böyle kodu görüyorum:

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

Ve tembel dillerin kullanıcıları bunu yapmaya cazip gelebilir:

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

Bunlar diğer dillerde de doğrudur. Ve bu Python'da anlamsal olarak doğrudur.

Ancak bunu Pythonic olarak düşünüyoruz, çünkü Python bu anlambilimi doğrudan liste nesnesinin arayüzünde boole zorlamasıyla destekliyor.

Gönderen docs (ve not boş listenin özellikle dahil, []):

Sınıf , nesne ile çağrıldığında, döndürülen bir yöntemi veya sıfır __bool__()döndüren bir yöntemi tanımlamazsa, varsayılan olarak bir nesne true olarak kabul edilir . Yanlış olarak kabul edilen yerleşik nesnelerin çoğu şunlardır:False__len__()

  • false olarak tanımlanan sabitler: NoneveFalse .
  • herhangi bir sayısal tür sıfır: 0, 0.0, 0j,Decimal(0) ,Fraction(0, 1)
  • Boş diziler ve koleksiyonlar: '', (), [], {}, set(),range(0)

Ve veri modeli belgeleri:

object.__bool__(self)

Gerçeğe uygun değer testi ve yerleşik işlemi uygulamaya çağırdı bool(); dönmeli Falseya daTrue . Bu yöntem tanımlanmadığında, tanımlanmışsa __len__()çağrılır ve sonucu sıfırdan farklıysa nesne true olarak kabul edilir. Bir sınıf ne __len__() de ne de tanımlarsa __bool__(), tüm örnekleri doğru kabul edilir.

ve

object.__len__(self)

Yerleşik işlevi uygulamak için çağrıldı len() . Nesnenin uzunluğunu döndürmelidir, tamsayı> = 0. Ayrıca, bir __bool__()yöntem tanımlamayan ve __len__()yöntemi sıfıra dönen bir nesne Boole bağlamında false olarak kabul edilir.

Bunun yerine:

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

veya bu:

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

Bunu yap:

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

Pythonic'i yapmak genellikle performansta işe yarar:

Ödeniyor mu? (Eşdeğer bir işlem gerçekleştirmek için daha az zamanın daha iyi olduğunu unutmayın :)

>>> 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

Ölçek için, işlevi çağırmanın ve yukarıda kullanılan boşluk kontrollerinin maliyetlerinden çıkarabileceğiniz boş bir liste oluşturma ve geri gönderme maliyeti aşağıdadır:

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

Biz görüyoruz , ya yerleşik fonksiyonu ile uzunluğu için kontrol lenile karşılaştırıldığında 0 ya boş bir listeye karşı kontrol ediyor çok yeterli performansı belgelendiği gibi dilin yerleşik sözdizimi kullanılarak daha.

Neden?

İçin len(a) == 0 çek:

İlk önce Python'un len gölgeli .

Daha sonra işlevi çağırmalı, yüklemeli 0ve Python'da eşitlik karşılaştırmasını yapmalıdır (C yerine):

>>> 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

Ve [] == []bunun için gereksiz bir liste oluşturmalı ve sonra tekrar Python'un sanal makinesinde karşılaştırma işlemini yapmalıdır (C yerine)

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

Listenin uzunluğu nesne örneği üstbilgisinde önbelleğe alındığından, "Pythonic" yolu çok daha basit ve hızlı bir denetimdir:

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

C kaynağından kanıtlar ve belgeler

PyVarObject

Bu alanı PyObjectekleyen bir uzantısıdır ob_size. Bu sadece uzunluk kavramına sahip nesneler için kullanılır. Bu tür genellikle Python / C API'sinde görünmez. PyObject_VAR_HEADMakronun genişlemesi ile tanımlanan alanlara karşılık gelir .

Include / listobject.h içindeki c kaynağından :

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

Yorumlara yanıt:

Bununla olarak oldukça çirkin olsa boş olmayan durum için de geçerli olduğunu işaret etmek isterim l=[]sonra %timeit len(l) != 090.6 ns ± 8.3 ns, %timeit l != []55.6 ns ± 3,09, %timeit not not l38.5 ns ± 0.372. Ancak not not lüçlü hıza rağmen kimsenin zevk alacağı bir yol yoktur . Saçma görünüyor. Ancak hız
kazanır.Sorun if l:yeterli olduğunu, ancak şaşırtıcı bir şekilde %timeit bool(l)101 ns ± 2.64 ns verdiğinden problemin timeit ile test edildiğini düşünüyorum . İlginçtir, bu ceza olmadan boole zorlanmanın bir yolu yoktur. %timeit lhiçbir dönüşüm gerçekleşmeyeceğinden yararsızdır.

IPython büyüsü,, %timeitburada tamamen işe yaramaz:

In [1]: l = []                                                                  

In [2]: %timeit l                                                               
20 ns ± 0.155 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)

In [3]: %timeit not l                                                           
24.4 ns ± 1.58 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [4]: %timeit not not l                                                       
30.1 ns ± 2.16 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

notBurada her bir ek için biraz doğrusal maliyet olduğunu görebiliriz. Maliyetleri, ceteris paribus'u , yani her şeyin eşit olduğunu görmek istiyoruz - diğer her şey mümkün olduğunca en aza indirilmiştir:

In [5]: %timeit if l: pass                                                      
22.6 ns ± 0.963 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [6]: %timeit if not l: pass                                                  
24.4 ns ± 0.796 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [7]: %timeit if not not l: pass                                              
23.4 ns ± 0.793 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

Şimdi bir işsizlik listesi için duruma bakalım:

In [8]: l = [1]                                                                 

In [9]: %timeit if l: pass                                                      
23.7 ns ± 1.06 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [10]: %timeit if not l: pass                                                 
23.6 ns ± 1.64 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [11]: %timeit if not not l: pass                                             
26.3 ns ± 1 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

Burada görebildiğimiz, gerçek bir şekilde geçip geçmemenizin çok az fark yaratmasıdır bool şey, durum kontrolüne veya listenin kendisine şekilde geçmemeniz ve listeyi olduğu gibi veren herhangi bir şeyin daha hızlı olması fark etmez.

Python C dilinde yazılmıştır; mantığını C düzeyinde kullanır. Python'da yazdığınız her şey daha yavaş olacaktır. Doğrudan Python'da yerleşik mekanizmaları kullanmadığınız sürece büyük olasılıkla daha yavaş emirler olacaktır.


Bununla olarak oldukça çirkin olsa boş olmayan durum için de geçerli olduğunu işaret etmek isterim l=[]sonra %timeit len(l) != 090.6 ns ± 8.3 ns, %timeit l != []55.6 ns ± 3,09, %timeit not not l38.5 ns ± 0.372. Ancak not not lüçlü hıza rağmen kimsenin zevk alacağı bir yol yoktur . Saçma görünüyor. Ama hız kazanıyor
Gregory Morse

Sanırım problem sadece timeit ile test ediliyor çünkü sadece if l:yeterli ama şaşırtıcı bir şekilde %timeit bool(l)101 ns ± 2.64 ns veriyor. İlginçtir, bu ceza olmadan boole zorlanmanın bir yolu yoktur. %timeit lhiçbir dönüşüm gerçekleşmeyeceğinden yararsızdır.
Gregory Morse

138

Gerçek değer testinde boş bir listenin kendisi yanlış kabul edilir ( python belgelerine bakın ):

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

@Daren Thomas

EDIT: boş liste yanlış olarak test karşı başka bir nokta: Polimorfizm hakkında ne? Liste olan bir listeye bağımlı olmamalısınız. Sadece bir ördek gibi quack yapmalı - ördekinizi nasıl toplayacaksınız?

Kişisel duckCollection uygulamalıdır __nonzero__veya __len__bir eğer öyleyse: sorunsuz çalışacaktır.


Garip nasıl [] == Falseyanlış olarak değerlendirir
information_interchange

@ info_interchange Bir değerin gerçekliğini açıkça kontrol etmek istiyorsanız, kullanın bool(). beklendiği gibi bool([]) == Falsedeğerlendirir True.
augurar

103

Patrick'in (kabul edilen) cevabı doğrudur: if not a:bunu yapmanın doğru yolu. Harley Holcombe'un cevabı , bunun PEP 8 stil kılavuzunda olduğu doğru. Ancak cevapların hiçbirinin açıklayamadığı şey, deyimi takip etmenin neden iyi bir fikir olduğudur - kişisel olarak Ruby kullanıcıları veya herhangi bir şey için yeterince açık veya kafa karıştırıcı olmasanız bile.

Python kodu ve Python topluluğu çok güçlü deyimlere sahiptir. Bu deyimleri izlemek, Python'da deneyimli herkes için kodunuzun okunmasını kolaylaştırır. Ve bu deyimleri ihlal ettiğinizde, bu güçlü bir sinyaldir.

Bu doğrudur if not a:gelen boş listeleri ayrım yapmaz NoneFalsey ile skalerler görevi görmek veya sayısal 0 veya boş dizilerini veya boş kullanıcı tarafından oluşturulan koleksiyon türleri veya boş kullanıcı tarafından oluşturulan değil oldukça toplama türleri veya tek eleman NumPy dizi Ve bazen bu konuda açık olmak önemlidir. Ve bu durumda, ne hakkında açık olmak istediğinizi biliyorsunuz , böylece tam olarak bunu test edebilirsiniz. Örneğin, if not a and a is not None:"Hiçbiri dışında falsey olan herhangi bir şey" if len(a) != 0:anlamına gelirken , "yalnızca boş diziler - ve bir dizinin dışındaki her şey burada bir hatadır" anlamına gelir. Tam olarak ne test etmek istediğinizi test etmenin yanı sıra bu, okuyucuya bu testin önemli olduğunu da gösterir.

Ancak, açıklanacak bir şeyiniz olmadığında if not a:, okuyucuyu yanlış yönlendirmekten başka bir şey yoktur . Önemli olmadığında önemli bir şeye işaret ediyorsun. (Ayrıca kodu daha az esnek, daha yavaş veya her neyse yapıyor olabilirsiniz, ancak bunların hepsi daha az önemlidir.) Ve okuyucuyu böyle alışkanlıkla yanlış yönlendirirseniz, bir ayrım yapmanız gerektiğinde, fark edilmeden geçecektir, çünkü kodunun her yerinde "ağlayan kurt" oldun.


78

Neden hiç kontrol etmiyorsun?

Kimse listeyi ilk etapta test etme ihtiyacınızı sorgulamış gibi görünmüyor . Başka bir bağlam sağlamadığınız için, bu kontrolü ilk etapta yapmanız gerekmeyebileceğini, ancak Python'daki liste işlemeyi bilmediğinizi hayal edebiliyorum.

En pitonik yolun hiç kontrol etmek değil, sadece listeyi işlemek olduğunu iddia ediyorum . Bu şekilde boş veya dolu olsun doğru olanı yapar.

a = []

for item in a:
    <do something with item>

<rest of code>

Bu herhangi içeriğini ele yararı vardır bir boşluk için belirli bir çek ihtiyaç duymaz,. Eğer bir boş, bağımlı blok yürütmek olmaz ve tercüman sonraki satıra yoluyla düşecek.

Diziyi boşluk için kontrol etmeniz gerekiyorsa, diğer cevaplar yeterlidir.


3
Mesele şu ki, listenin boş olup olmadığını kontrol et, en azından benim için oldukça önemli. İçinde döngüdeki <rest of code>sonucu kullanabilen bir komut dosyası olup olmadığını düşündünüz formü? Ya da doğrudan bazı değerleri a? Gerçekten de, komut dosyası tam denetimli girdiyle çalışacak şekilde tasarlanmışsa, denetim biraz gereksiz olabilir. Ancak çoğu durumda, giriş değişir ve bir kontrole sahip olmak genellikle daha iyidir.
Amarth Gûl

Saygılarımla, hayır. Benim düşündüğüm, Python hakkında “<list>:” ifadesinin doğru yanıt olduğunu bilmesi için yeterli bilgiye sahip olmayan, boş bir listeyi nasıl kontrol edeceğini sordu. Sonra farklı görüşler sunan bir sürü cevap fark ettim, ancak hiçbiri orijinal ihtiyacı karşılamıyordu. Cevabımla bunu yapmaya çalıştım - devam etmeden önce ihtiyacı incelemelerini sağlayın. Cevabımda açıkça önerdiğime inanıyorum.
MrWonderful

@ AmarthGûl - Nasıl işlenecek <kod geri kalanı> içinde for döngüsünün komut dosyasına sonuçları alabilir ? Bir listede, belki? Ya da belki bir diksiyon? Eğer öyleyse, aynı mantık geçerlidir. Değişken girdinin , boş bir listeyi işlemenin kötü bir fikir olacağı, makul şekilde tasarlanmış herhangi bir kod içinde nasıl bir etkisi olabileceğini anlamıyorum .
MrWonderful

Biraz eski ama sadece listenin boş olup olmadığını kontrol ediyor olsaydınız, boş olmayan bir liste için OP sadece bir kontrol işlemi ararken işlemi tekrar eder. N sonsuzluğa yaklaşırken bu kod için daha kötü bir senaryo düşünün ....
DJK

7
@DJK - Hayır, sanırım hala özlüyorsun. Muhtemelen bir listeniz varsa, bir listeyle bir şeyler yapmak istersiniz. Boş olsaydı ne yapardın? Erken dönüyor musunuz? Boş değilse ne olur? işlemek? Mesele şu ki, muhtemelen boş bir listeyi kontrol etmeniz gerekmiyor, sadece onu tekrarlayın ve elementlerle ne yapacağınızı yapın . Eleman yoksa, düşersiniz. Elemanlar varsa, bunları gerektiği gibi işlersiniz. Mesele, boş kontrol FOR örneğini kullanmak DEĞİLDİR, daha ziyade hiç kontrol ETMEMEKTEDİR, sadece listeyi işleyin.
MrWonderful


40

Yazdım:

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

-1 oylandı. Bunun okuyucuların stratejiye itiraz etmeleri veya cevabın sunulduğu gibi yardımcı olmadığını düşündüklerinden emin değilim. İkincisi gibi davranacağım, çünkü "pythonic" olarak sayılan her şey --- bu doğru stratejidir. Önceden dışlanmış değilseniz veya aörneğin davaları ele almaya hazır Falsedeğilseniz, sadece testten daha kısıtlayıcı bir teste ihtiyacınız vardır if not a:. Bunun gibi bir şey kullanabilirsiniz:

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

ilk test yukarıdaki @ Mike'ın cevabına yanıt olarak verilmiştir. Üçüncü satır da şu şekilde değiştirilebilir:

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

yalnızca belirli türlerin (ve alt türlerinin) örneklerini kabul etmek istiyorsanız veya aşağıdakilerle:

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

Açık tür denetimi olmadan kurtulabilirsiniz, ancak yalnızca çevredeki içerik zaten sizi güvence altına alıyorsa, bu aişlemeye hazır olduğunuz türlerin bir değeridir veya işlemeye hazır olmadığınız türlerin gittiğinden eminseniz işlemeye hazır olduğunuz hataları (ör. tanımsız olduğu bir değeri TypeErrorçağırırsanız) yükseltmek leniçin. Genel olarak, "pitonik" konvansiyonlar bu şekilde yürüyor gibi görünüyor. Ördek gibi sıkın ve nasıl quack yapacağını bilmiyorsa bir DuckError yükseltmesine izin verin. Hala düşünmek zorundasınız hakkında ne tür varsayımlar sen yapma olsa ve düzgün gerçekten işlemek için hazır değilsin doğru yerlere dışarı hata olacak durumlarda olmadığına. Numpy dizileri sadece körü körüne güvenen iyi bir örnektirlen ya da boolean typecast tam olarak beklediğinizi yapmayabilir.


3
Kabul etmek istediğiniz 6 türden oluşan kapsamlı bir listeye sahip olmanız ve diğer türler için esnek olmamanız oldukça nadirdir. Bu tür bir şeye ihtiyacınız olduğunda, muhtemelen bir ABC istersiniz. Bu durumda, muhtemelen collections.abc.Sizedveya gibi stdlib ABC'lerinden biri olacaktır collections.abc.Sequence, ancak kendiniz ve register(list)üzerinde yazdığınız biri olabilir . Aslında boş diğer falseyden ayırmak ve aynı zamanda listeleri ve tuples diğer dizileri ayırt etmek önemli olan kod varsa, o zaman bu doğru - ama böyle bir kod olduğuna inanmıyorum.
abarnert

13
İnsanların bunu sevmemesinin nedeni, çoğu durumda tamamen unnessesic olmasıdır. Python ördek tipi bir dildir ve bu savunma kodlama seviyesi aktif olarak bunu engeller. Python'un tip sisteminin arkasındaki fikir, nesne işlevlerde ihtiyaç duyulduğu şekilde geçtiği sürece işlerin çalışması gerektiğidir. Açık tür denetimleri yaparak, arayanı belirli türler kullanmaya zorlarsınız, dilin tam karşılığını alırsınız. Bazen bu tür şeyler gerekli olsa da (dizelerin diziler olarak ele alınmasını hariç tutmak), bu gibi durumlar nadirdir ve neredeyse her zaman kara listeler olarak en iyisidir.
Gareth Latty

1
Gerçekten değerin tam olarak []başka bir türden bir şey olmadığını kontrol etmek istiyorsanız if a == []:, isinstance ile mucking yerine mutlaka çağrılır.
RemcoGerlich

2
Yine de bazı otomatik zorlamalar vardır ==. Başımın üstünden, herhangi birini tanımlayamıyorum []. [] == ()örneğin geri döner False. Ancak, örneğin frozenset()==set()geri döner True. Bu nedenle, en azından bazı istenmeyen tiplerin zorlanıp zorlanmayacağı [](veya tersi) olup olmadığı konusunda biraz düşünmeye değer a == [].
dubiousjim

@RemcoGerlich - isinstance (), karşılaştırılacak boş bir liste oluşturmak yerine hala tercih edilmektedir. Ayrıca, bir diğerinin de işaret ettiği gibi, eşitlik operatörü, bazı türlerin, istenmeyen olabilecek örtük dönüşümü başlatabilir. Hiçbir zaman "a == []" kodlamak için bir neden yoktur ve bu kod katıldığım herhangi bir kod incelemesinde kesinlikle bir hata olarak işaretlenir. , "daha ziyade" iyi programlama tekniği. "
MrWonderful

29

Gönderen belgelere doğruluk değeri testlere:

Burada listelenenler dışındaki tüm değerler dikkate alınır True

  • None
  • False
  • herhangi bir sayısal tür sıfır, örneğin 0, 0.0, 0j.
  • boş bir sıra, örneğin, '', (), [].
  • herhangi bir boş eşleme, örneğin {}.
  • sınıf bir __bool__()veya __len__()yöntemi tanımlarsa , bu yöntem tamsayı sıfır veya bool değeri döndürdüğünde, kullanıcı tanımlı sınıf örnekleri False.

Görüldüğü üzere, boş liste []olduğunu falsy , en verimli bir boolean değer seslere yapılması ne yapıyor bu yüzden:

if not a:
    print('"a" is empty!')

@DJ_Stuffy_K, birim testinde boş bir liste olduğunu iddia ediyor mu? Sadece kullan assert(not myList). Ayrıca nesnenin bir olduğunu iddia etmek lististiyorsanız, kullanabilirsiniz assertIsInstance().
Sнаđошƒаӽ

24

Bir listenin boş olup olmadığını kontrol etmenin birkaç yolu:

a = [] #the list

1) Oldukça basit pitonik yol:

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

Python'da liste, tuples, küme, dikte, değişken vb . Gibi boş kaplar olarak görülür False. Listeyi yüklem ( Boole değeri döndüren) olarak ele almak yeterlidir . Ve bir Truedeğer boş olmadığını gösterir.

2) Çok açık bir yol: len()uzunluğu bulmak ve eşit olup olmadığını kontrol etmek için 0:

if len(a) == 0:
    print("a is empty")

3) Veya isimsiz bir boş listeyle karşılaştırılması:

if a == []:
    print("a is empty")

4) Bir başka henüz saçma do yolu kullanıyor exceptionve iter():

try:
    next(iter(a))
    # list has elements
except StopIteration:
    print("Error: a is empty")

20

Aşağıdakileri tercih ederim:

if a == []:
   print "The list is empty."

37
Gereksiz yere ekstra boş bir liste başlattığınız için bu daha yavaş olacaktır.
Carl Meyer

32
bu daha az okunabilir if not a:ve daha kolay kırılır. Lütfen yapma.
devsnd

Daha önce () == []de yanlış olana eşit olan iyi bir nokta vardır . Bu uygulamanın if not a:tüm vakaları nasıl okuduğunu sevsem de , kesinlikle bir liste bekliyorsanız, o zaman örneğiniz yeterli olmalıdır.
Bir Yıldız

19

Yöntem 1 (Tercih Edilen):

if not a : 
   print ("Empty") 

Yöntem 2:

if len(a) == 0 :
   print( "Empty" )

Yöntem 3:

if a == [] :
  print ("Empty")

12
def list_test (L):
    if   L is None  : print('list is None')
    elif not L      : print('list is empty')
    else: print('list has %d elements' % len(L))

list_test(None)
list_test([])
list_test([1,2,3])

Bazen Noneiki farklı durum olduğu için boşlukları ayrı ayrı test etmek ve denemek iyi olabilir . Yukarıdaki kod aşağıdaki çıktıyı üretir:

list is None 
list is empty 
list has 3 elements

Her ne kadar bir şey Nonedeğersiz olsa da. Eğer test için Noneayrılık istemiyorsanız, bunu yapmak zorunda değilsiniz.

def list_test2 (L):
    if not L      : print('list is empty')
    else: print('list has %d elements' % len(L))

list_test2(None)
list_test2([])
list_test2([1,2,3])

beklenen üretim

list is empty
list is empty
list has 3 elements

8

Birçok cevap verildi ve birçoğu oldukça iyi. Sadece çeki eklemek istedim

not a

Noneve diğer boş yapı türlerini de geçecektir . Gerçekten boş bir liste olup olmadığını kontrol etmek istiyorsanız, bunu yapabilirsiniz:

if isinstance(a, list) and len(a)==0:
    print("Received an empty list")

aListe değilse ve aherhangi bir yöntem __len__uygulanmadıysa , bunun bir istisna atması mümkündür . Tavsiye ederim:if isinstance(obj, list): if len(obj) == 0: print '...'
Sven Krüger

4
@ SvenKrüger hayır. Operatör andPython'da tembel. Daha andönce koşul Yanlışsa, hiçbir şey yürütülmez and.
ElmoVanKielmo

7

başka bir basit kullanabiliriz:

item_list=[]
if len(item_list) == 0:
    print("list is empty")
else:
    print("list is not empty")

5
-1 - Karışıklığı önlemek için değişken adları için ayrılmış kelimeler kullanmayın veya bir dahaki sefere aramaya çalıştığınızda şaşırtıcı bir davranış yaşayabilirsiniz, örneğin "list ()" ... "TypeError: 'list' nesnesi çağrılabilir değil "veya benzeri.
MrWonderful

6

Bir listenin boş olup olmadığını kontrol etmek istiyorsanız:

l = []
if l:
    # do your stuff.

Listedeki tüm değerlerin boş olup olmadığını kontrol etmek istiyorsanız. Ancak Trueboş bir liste olacaktır:

l = ["", False, 0, '', [], {}, ()]
if all(bool(x) for x in l):
    # do your stuff.

Her iki durumu da birlikte kullanmak istiyorsanız:

def empty_list(lst):
    if len(lst) == 0:
        return False
    else:
        return all(bool(x) for x in l)

Şimdi şunları kullanabilirsiniz:

if empty_list(lst):
    # do your stuff.

1
boş bir liste için tümü (bool (x) x için boş)
gberger

5

@ Dubiousjim'in çözümünden esinlenerek, tekrarlanabilir bir şey olup olmadığına dair ek bir genel kontrol kullanmayı öneriyorum

import collections
def is_empty(a):
    return not a and isinstance(a, collections.Iterable)

Not: Bir dize yinelenebilir olarak kabul edilir. - and not isinstance(a,(str,unicode))boş dizenin hariç tutulmasını istiyorsanız ekleyin

Ölçek:

>>> is_empty('sss')
False
>>> is_empty(555)
False
>>> is_empty(0)
False
>>> is_empty('')
True
>>> is_empty([3])
False
>>> is_empty([])
True
>>> is_empty({})
True
>>> is_empty(())
True

1
Çok geniş; bu sadece bir listenin boş olup olmadığını soruyor, bir şeyin boş bir yinelenebilir olup olmadığını sormuyor.
pppery

1
Eğer memnun if a:olmasaydım, bir açeşit konteyner olmasaydı istisna istedim . (Bir yinelenebilir olmak da boşluğu test etmek için yararlı olamaz yineleyiciler sağlar.)
Davis Herring

5
print('not empty' if a else 'empty')

biraz daha pratik:

a.pop() if a else None

ve shertest sürümü:

if a: a.pop() 

4

Python3'ten itibaren kullanabilirsiniz

a == []

listenin boş olup olmadığını kontrol etmek için

EDIT: Bu da python2.7 ile çalışır ..

Neden bu kadar karmaşık cevaplar olduğundan emin değilim. Oldukça açık ve anlaşılır


1
lütfen "if" yazmadan nasıl çalıştığı hakkında daha fazla açıklama yapın?
ganeshdeshmukh

3
Bu pitonik veya tam bir örnek değildir. Ayrıca, her karşılaşıldığında boş bir liste oluşturur. Bunu yapma.
MrWonderful

@MrWonderful her seferinde boş bir liste oluşturmaz. Sadece mevcut listenin aboş olup olmadığını doğrular .
Tessaracter

@MrWonderful Ne yapar anlamıyorumpythonic
Tessaracter

@ganeshdeshmukh kullanırsanız a==[], boşsa python terminalinde true yazdıracaktır. Aksi takdirde False yazdıracaktır. Bunu bir if durumunda da kullanabilirsinizif(a==[])
Tessaracter

3

Hatta böyle bool () kullanmayı deneyebilirsiniz

    a = [1,2,3];
    print bool(a); # it will return True
    a = [];
    print bool(a); # it will return False

Kontrol listesi boş ya da değil için bu şekilde seviyorum.

Çok kullanışlı ve kullanışlı.


4
Bilmeyenler için (benim gibi) bool()bir Python değişkenini bir boole'ye dönüştürür , böylece bir if ifadesini kullanmak zorunda kalmadan bir değerin gerçekliğini veya sahteliğini saklayabilirsiniz . Bence sadece kabul edilen cevap gibi bir koşul kullanmaktan daha az okunabilir, ancak bunun için başka iyi kullanım durumları olduğundan eminim.
Galen Long

Bu bir ifadede kullanılabilir ve daha keskindir.
qneill

3

Sadece is_empty () kullanın ya da aşağıdaki gibi bir işlev yapın: -

def is_empty(any_structure):
    if any_structure:
        print('Structure is not empty.')
        return True
    else:
        print('Structure is empty.')
        return False  

Liste, tuples, sözlük ve daha fazlası gibi herhangi bir veri yapısı için kullanılabilir. Bunlarla, sadece kullanarak birçok kez arayabilirsiniz is_empty(any_structure).


3
İsim is_empty, bir şey döndürdüğünü gösterir. Ama eğer öyleyse, bool(any_structure)bunun yerine kullanmanız gereken bir şey olurdu ( hiç ihtiyacınız olduğundabool ).
Davis Herring

4
Neden bool(ayrıca) iletileri standart çıktıya yazdırırken bir varyasyon istiyoruz ?
Davis Herring

@DavisHerring Her zaman iki seçeneğimiz vardır, diğer işlevde dönüş booldeğişkeni kullanarak yazdırmaktır . Seçim senin. İkisini de yazıyorum, böylece aralarından seçim yapabilirsiniz.
Vineet Jain

3

Basit yolu uzunluğu eşit sıfır kontrol etmektir.

if len(a) == 0:
    print("a is empty")


1

Beni buraya getiren özel bir kullanım durumu: Aslında bir listenin boş olup olmadığını söylemek için bir işlev istedim . Kendi işlevimi yazmaktan veya burada bir lambda ifadesi kullanmaktan kaçınmak istedim (çünkü yeterince basit görünüyordu):

foo = itertools.takewhile(is_not_empty, (f(x) for x in itertools.count(1)))

Ve elbette, bunu yapmanın çok doğal bir yolu var:

foo = itertools.takewhile(bool, (f(x) for x in itertools.count(1)))

Tabii ki, do not kullanmak booliçinde if(yani if bool(L):o ima çünkü). Ancak, bir işlev olarak "boş olmayan" açıkça ihtiyaç duyulan durumlarda bool, en iyi seçimdir.


1

Bir listenin boş olup olmadığını kontrol etmek için aşağıdaki iki yolu kullanabilirsiniz. Ancak unutmayın, bir tür sekansı açıkça kontrol etmekten kaçınmalıyız (bu bir less pythonicyol):

def enquiry(list1): 
    if len(list1) == 0: 
        return 0
    else: 
        return 1

# ––––––––––––––––––––––––––––––––

list1 = [] 

if enquiry(list1): 
    print ("The list isn't empty") 
else: 
    print("The list is Empty") 

# Result: "The list is Empty".

İkinci yol more pythonicbirdir. Bu yöntem, örtük bir kontrol yöntemidir ve öncekinden çok daha fazla tercih edilir.

def enquiry(list1): 
    if not list1: 
        return True
    else: 
        return False

# ––––––––––––––––––––––––––––––––

list1 = [] 

if enquiry(list1): 
    print ("The list is Empty") 
else: 
    print ("The list isn't empty") 

# Result: "The list is Empty"

Bu yardımcı olur umarım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.