Gra adwokata diabła. Nie rozumiem, dlaczego ten idiom jest uważany za pytoniczny. „Jawne jest lepsze niż niejawne”, prawda? Ta kontrola nie wydaje się bardzo wyraźna na temat tego, co jest sprawdzane.
James McMahon
222
@JamesMcMahon - to kompromis między jawnością a elastycznością typu. ogólnie „bycie jawnym” oznacza nie robienie „magicznych” rzeczy. z drugiej strony „pisanie kaczką” oznacza pracę z bardziej ogólnymi interfejsami, zamiast jawnego sprawdzania typów. więc coś takiego if a == []wymusza określony typ ( () == []jest False). tutaj ogólny konsensus wydaje się być taki, że wygrywa pisanie kaczek (w efekcie mówiąc, że __nonzero__jest to interfejs do testowania pustki docs.python.org/reference/datamodel.html#object.__nonzero__ )
andrew cooke
38
Ta metoda nie działa na tablicach numpy. Myślę, że jeśli len (a) == 0 jest preferowany zarówno pod względem „pisania kaczego”, jak i niejawności.
Mr.WorshipMe
10
Kanonicznym sposobem sprawdzenia, czy tablica w C jest pusta, jest usunięcie dereferencji z pierwszego elementu i sprawdzenie, czy jest ona pusta, przy założeniu, że tablica jest zakończona zerem. W przeciwnym razie porównanie jego długości do zera jest całkowicie nieefektywne, jeśli tablica ma znaczny rozmiar. Zazwyczaj nie przydziela się pamięci dla pustej tablicy (wskaźnik pozostaje pusty), więc nie ma sensu próbować uzyskać jej długości. Nie twierdzę, że len (a) == 0 nie jest dobrym sposobem na zrobienie tego, po prostu nie krzyczy do mnie „C”, kiedy go widzę.
sleblanc
6
@BrennenSprimont, Jeśli nie jest zakończony zerem, oznacza to, że znasz już długość, czy jest ona przechowywana w osobnej zmiennej, czy twoja tablica jest zapakowana w jakiś kontener, który śledzi długość. C ++, Java, C # mają takie kontenery i skutecznie implementują metodę „length”. C nie ma czegoś takiego , musisz rzucić własnym. Statycznie przydzielone tablice C są tylko wskaźnikami do obszaru pamięci, który gwarantuje wystarczającą ilość miejsca do przechowywania żądanej ilości danych. Nie ma nic wbudowanego w C, co dałoby ci znać, ile już wypełniłeś to miejsce.
sleblanc
1158
Pythoniczny sposób na to jest z przewodnika po stylu PEP 8 (gdzie „ Tak ” oznacza „zalecane”, a „ Nie ” oznacza „niezalecane”):
W przypadku sekwencji (ciągów, list, krotek) użyj faktu, że puste sekwencje są fałszywe.
Drugi sposób wydaje się lepszy, jeśli chcesz zasygnalizować, że seqma to być obiekt listy.
BallpointBen
5
@BallpointBen, który, jak twierdzą zwolennicy Pythonizmu, powinien być domyślnie imitowany tak, jak nazywa się zmienną, w jak największym stopniu
axolotl
9
@BallpointBen spróbuj użyć podpowiedzi typu Python do zasygnalizowania, jaka powinna być zmienna. Został wprowadzony w wersji 3.5.
Boris
8
numpy złamał ten idiom ... seq = numpy.array ([1,2,3]), a następnie jeśli nie seq podnosi wyjątek "ValueError: Wartość prawdy tablicy z więcej niż jednym elementem jest niejednoznaczna. Użyj a.any () lub a.all () ”
Mr.WorshipMe
2
@jeronimo: Uważam, że jest to ostrzeżenie specyficzne dla lxml.
Harley Holcombe
767
Wolę to wyraźnie:
if len(li)==0:print('the list is empty')
W ten sposób jest w 100% jasne, że lijest to sekwencja (lista) i chcemy przetestować jej rozmiar. Mój problem if not li: ...polega na tym, że daje fałszywe wrażenie, że lijest zmienną logiczną.
Sprawdzanie, czy długość listy jest równa zeru, zamiast tylko sprawdzania, czy lista jest fałszywa, jest brzydka i pozbawiona mitów. Każdy, kto zna Python, w ogóle nie pomyśli, że lito bool, i nie będzie go to obchodzić. Jeśli to ważne, powinieneś dodać komentarz, a nie więcej kodu.
Carl Smith,
21
Wydaje się to niepotrzebnie precyzyjnym testem, który często jest wolniejszy i zawsze jest mniej czytelny IMHO. Zamiast sprawdzać rozmiar czegoś pustego, dlaczego po prostu nie sprawdzić, czy jest pusty?
John B,
34
W każdym razie powodem, dla którego jest to złe (i że naruszanie idiomów w języku z silnymi idiomami, takimi jak Python, jest ogólnie złe) jest to, że sygnalizuje czytelnikowi, że z jakiegoś powodu konkretnie sprawdzasz długość (np. Dlatego, że chcesz Nonelub 0zamiast stawiać wyjątek). Tak więc, gdy robisz to bez powodu, to jest mylące, a to oznacza również, że gdy Twój kod ma potrzeby wprowadzania rozróżnienia, rozróżnienie jest niewidoczny, ponieważ masz „Płakał wilk” całej reszty źródła.
abarnert
18
Myślę, że to po prostu niepotrzebnie wydłuża kod. W przeciwnym razie, dlaczego nie być jeszcze bardziej „wyraźnym” if bool(len(li) == 0) is True:?
sierpień
11
@Jabba będzie to O (1) w wielu przypadkach (te, w których pracujesz z wbudowanymi typami danych), ale po prostu nie możesz na tym polegać. Być może pracujesz z niestandardowym typem danych, który nie ma tej właściwości. Możesz również zdecydować o dodaniu tego niestandardowego typu danych później, po napisaniu tego kodu.
ralokt
324
To jest pierwsze trafienie w Google dla „pustej tablicy Pythona” i podobnych zapytań, a inni wydają się uogólniać pytanie poza tylko listami, więc pomyślałem, że dodam zastrzeżenie dla innego rodzaju sekwencji, niż wiele osób może użyć.
Inne metody nie działają dla tablic NumPy
Trzeba uważać na tablice NumPy, ponieważ inne metody, które działają dobrze dla lists lub innych standardowych kontenerów, zawodzą w przypadku tablic NumPy. Wyjaśniam dlaczego, ale w skrócie, preferowaną metodą jest użycie size.
„Pythonowy” sposób nie działa: Część 1
Metoda „pytoniczna” kończy się niepowodzeniem w przypadku tablic NumPy, ponieważ NumPy próbuje rzutować tablicę na tablicę bools i if xpróbuje ocenić wszystkie te wartości boolnaraz dla pewnego rodzaju zagregowanej wartości prawdy. Ale to nie ma sensu, więc otrzymujesz 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()
Sposób „pythonowy” nie działa: część 2
Ale przynajmniej powyższy przypadek mówi ci, że się nie udało. Jeśli zdarzy ci się, że masz tablicę NumPy z dokładnie jednym elementem, ifinstrukcja będzie „działać” w tym sensie, że nie otrzymasz błędu. Jeśli jednak tym elementem będzie 0(lub 0.0, lub False...), ifinstrukcja niepoprawnie spowoduje False:
>>> x = numpy.array([0,])>>>if x:print("x")...else:print("No x")No x
Ale wyraźnie xistnieje i nie jest pusty! Ten wynik nie jest tym, czego chciałeś.
Korzystanie lenmoże dać nieoczekiwane rezultaty
Na przykład,
len( numpy.zeros((1,0)))
zwraca 1, mimo że tablica zawiera zero elementów.
Sposób numpythonic
Jak wyjaśniono w SciPy FAQ , poprawną metodą we wszystkich przypadkach, w których wiesz, że masz tablicę NumPy, jest użycie 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
Jeśli nie masz pewności, czy może to być listtablica NumPy, czy coś innego, możesz połączyć to podejście z odpowiedzią podaną przez @dubiousjim, aby upewnić się, że dla każdego typu zastosowano odpowiedni test. Niezbyt „pythoniczny”, ale okazuje się, że NumPy celowo złamał pythonicity przynajmniej w tym sensie.
Jeśli trzeba zrobić więcej niż po prostu sprawdzić, czy wkład jest pusty, a używasz innego NumPy takich jak operacje indeksowania lub matematycznych, to chyba bardziej wydajne (a na pewno bardziej powszechne), aby wymusić wejście do być tablicą NumPy. Jest kilka fajnych funkcji umożliwiających szybkie wykonanie tego - co najważniejsze numpy.asarray. To pobiera dane wejściowe, nie robi nic, jeśli jest już tablicą, lub zawija dane wejściowe w tablicę, jeśli jest to lista, krotka itp., I opcjonalnie konwertuje ją na wybraną dtype. Jest więc bardzo szybki, gdy tylko jest to możliwe, i zapewnia, że po prostu przyjmiesz, że dane wejściowe to tablica NumPy. Zwykle używamy nawet tej samej nazwy, ponieważ konwersja na tablicę nie spowoduje, że znajdzie się poza bieżącym zakresem :
x = numpy.asarray(x, dtype=numpy.double)
Sprawi to, że x.sizeczek zadziała we wszystkich przypadkach, które widzę na tej stronie.
Warto zauważyć, że nie jest to wada w Pythonie, ale celowe zerwanie kontraktu przez numpy- numpyjest biblioteką z bardzo konkretnym przypadkiem użycia i ma inną „naturalną” definicję prawdziwości tablicy Standard Python dla kontenerów. To ma sens, aby zoptymalizować dla tego przypadku, w sposób, który pathlibużywa /do łączenia ścieżek zamiast +- to nietypowe, ale ma sens w kontekście.
Gareth Latty
9
Zgoda. Chodzi mi o to, że ważne jest, aby pamiętać, że numpy zdecydowało się złamać pisanie kaczych zarówno dla bardzo powszechnych, jak if xi len(x)idiomów - a czasami to złamanie może być bardzo trudne do wykrycia i debugowania.
Mike
22
Nie wiem dla mnie, czy metoda o nazwie len (x) nie zwraca długości tablicy, ponieważ założenia, jej nazwa jest źle zaprojektowana.
Dalton,
11
To pytanie nie ma nic wspólnego z tablicami
numpy
19
@ppperry Tak, pierwotne pytanie nie dotyczyło tablic Numpy, ale podczas pracy z tymi i, być może, argumentami typu kaczego, pytanie to staje się bardzo istotne.
peterhil
222
Najlepszy sposób na sprawdzenie, czy lista jest pusta
Na przykład, jeśli przekazano następujące:
a =[]
Jak sprawdzić, czy a jest pusty?
Krótka odpowiedź:
Umieść listę w kontekście logicznym (na przykład za pomocą instrukcji iflub while). Będzie sprawdzał, Falseczy jest pusty, i Trueinaczej. Na przykład:
ifnot a:# do this!print('a is an empty list')
PEP 8
PEP 8 , oficjalny przewodnik po języku Python dla kodu Python w standardowej bibliotece Pythona, zapewnia:
W przypadku sekwencji (ciągów, list, krotek) użyj faktu, że puste sekwencje są fałszywe.
Powinniśmy oczekiwać, że standardowy kod biblioteki powinien być tak wydajny i poprawny, jak to możliwe. Ale dlaczego tak jest i dlaczego potrzebujemy tych wskazówek?
Wyjaśnienie
Często widzę taki kod od doświadczonych programistów początkujących w Pythonie:
if len(a)==0:# Don't do this!print('a is an empty list')
A użytkownicy leniwych języków mogą ulec pokusie:
if a ==[]:# Don't do this!print('a is an empty list')
Są poprawne w swoich odpowiednich językach. Jest to nawet semantycznie poprawne w Pythonie.
Ale uważamy to za nie-Pythonic, ponieważ Python obsługuje tę semantykę bezpośrednio w interfejsie obiektu listy za pomocą logicznego koercji.
Z dokumentów (i zwróć uwagę na włączenie pustej listy []):
Domyślnie obiekt jest uważany za prawdziwy, chyba że jego klasa definiuje __bool__()metodę zwracającą Falselub __len__()metodę zwracającą zero, gdy zostanie wywołana z obiektem. Oto większość wbudowanych obiektów uznanych za fałszywe:
stałe zdefiniowane jako fałsz: Nonei False.
zera każdego typu numerycznej 0, 0.0, 0j, Decimal(0),Fraction(0, 1)
Puste sekwencje i kolekcje: '', (), [], {}, set(),range(0)
Wezwany do wdrożenia testowania wartości prawdy i wbudowanej operacji bool(); powinien wrócić Falselub True. Gdy ta metoda nie jest zdefiniowana,
__len__()jest wywoływana, jeśli jest zdefiniowana, a obiekt jest uważany za prawdziwy, jeśli jego wynik jest niezerowy. Jeśli klasa nie definiuje ani, __len__()
ani __bool__()wszystkie jej instancje są uważane za prawdziwe.
Wywoływany w celu wdrożenia wbudowanej funkcji len(). Powinna zwracać długość obiektu, liczba całkowita> = 0. Również obiekt, który nie definiuje __bool__()metody i którego __len__()metoda zwraca zero, jest uważany za fałsz w kontekście boolowskim.
Zamiast tego:
if len(a)==0:# Don't do this!print('a is an empty list')
albo to:
if a ==[]:# Don't do this!print('a is an empty list')
Zrób to:
ifnot a:print('a is an empty list')
Robienie tego, co Pythonic zwykle się opłaca:
Czy to się opłaca? (Pamiętaj, że krótszy czas na wykonanie równoważnej operacji jest lepszy :)
Widzimy, że albo sprawdzanie na długości za pomocą funkcji wbudowanej lenw porównaniu do 0lub sprawdzenie przed pustym liście jest znacznie mniej wydajnych niż przy użyciu składni wbudowanego języka jako udokumentowane.
Dlaczego?
Do len(a) == 0kontroli:
Najpierw Python musi sprawdzić globale, aby zobaczyć, czy lenjest zacieniony.
Następnie musi wywołać funkcję, załadować 0i wykonać porównanie równości w Pythonie (zamiast z C):
Aby to [] == []zrobić, musi zbudować niepotrzebną listę, a następnie ponownie wykonać operację porównania na maszynie wirtualnej Pythona (w przeciwieństwie do C)
To rozszerzenie PyObjectdodaje ob_sizepole. Jest to używane tylko w przypadku obiektów o pewnym znaczeniu długości. Ten typ często nie pojawia się w interfejsie API języka Python / C. Odpowiada polom zdefiniowanym przez rozwinięcie PyObject_VAR_HEADmakra.
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
Odpowiedź na komentarze:
By wskazać, że jest to również prawdziwe w odniesieniu do Niepuste przypadku chociaż jest dość brzydka przy l=[]czym %timeit len(l) != 090,6 NS NS ± 8,3, %timeit l != []55,6 ± 3,09 ns, %timeit not not l38,5 ± 0,372 ns. Ale nie ma mowy, aby ktokolwiek mógł się cieszyć not not lpomimo potrójnej prędkości. To wygląda niedorzecznie. Ale prędkość wygrywa.
Przypuszczam, że problem polega na testowaniu z czasem, ponieważ if l:jest po prostu wystarczający, ale zaskakująco %timeit bool(l)daje 101 ns ± 2,64 ns. Ciekawe, że bez tej kary nie można zmusić do buntu. %timeit ljest bezużyteczny, ponieważ nie nastąpiłaby konwersja.
Magia IPython %timeitnie jest tutaj całkowicie bezużyteczna:
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 notnot l
30.1 ns ±2.16 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)
Widzimy tutaj trochę liniowego kosztu każdego dodatkowego not. Chcemy, aby koszty, ceteris paribus , to znaczy wszystkie inne były równe - gdzie wszystko inne jest zminimalizowane w największym możliwym stopniu:
In[5]:%timeit if l:pass22.6 ns ±0.963 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)In[6]:%timeit ifnot l:pass24.4 ns ±0.796 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)In[7]:%timeit ifnotnot l:pass23.4 ns ±0.793 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)
Teraz spójrzmy na przypadek niepustej listy:
In[8]: l =[1]In[9]:%timeit if l:pass23.7 ns ±1.06 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)In[10]:%timeit ifnot l:pass23.6 ns ±1.64 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)In[11]:%timeit ifnotnot l:pass26.3 ns ±1 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)
Widzimy tutaj, że nie ma większego znaczenia, czy przekazujesz rzeczywiste boolsprawdzenie stanu, czy samą listę, a jeśli tak, to podanie listy, tak jak jest, jest szybsze.
Python jest napisany w C; używa swojej logiki na poziomie C. Wszystko, co napiszesz w Pythonie, będzie wolniejsze. I prawdopodobnie będzie to rząd wielkości wolniejszy, chyba że użyjesz mechanizmów wbudowanych bezpośrednio w Pythona.
By wskazać, że jest to również prawdziwe w odniesieniu do Niepuste przypadku chociaż jest dość brzydka przy l=[]czym %timeit len(l) != 090,6 NS NS ± 8,3, %timeit l != []55,6 ± 3,09 ns, %timeit not not l38,5 ± 0,372 ns. Ale nie ma mowy, aby ktokolwiek mógł się cieszyć not not lpomimo potrójnej prędkości. To wygląda niedorzecznie. Ale prędkość wygrywa
Gregory Morse
Przypuszczam, że problem polega na testowaniu z czasem, ponieważ if l:jest po prostu wystarczający, ale zaskakująco %timeit bool(l)daje 101 ns ± 2,64 ns. Ciekawe, że bez tej kary nie można zmusić do buntu. %timeit ljest bezużyteczny, ponieważ nie nastąpiłaby konwersja.
Gregory Morse
138
Pusta lista sama w sobie jest uważana za fałszywą podczas testowania prawdziwej wartości (patrz dokumentacja Pythona ):
a =[]if a:print"not empty"
@Daren Thomas
EDYCJA: Kolejny argument przeciwko testowaniu pustej listy jako False: A co z polimorfizmem? Nie powinieneś polegać na tym, że lista jest listą. Powinien po prostu kwakać jak kaczka - jak zamierzasz nakłonić swoją kaczkę do kolekcjonowania „Fałszywego”, gdy nie ma żadnych elementów?
Twój duckCollection powinny wdrożyć __nonzero__lub __len__więc jeśli: będzie działać bez problemów.
@information_interchange Jeśli chcesz jawnie sprawdzić prawdziwość wartości, użyj bool(). bool([]) == Falseoceni Truezgodnie z oczekiwaniami.
sierpień
103
Odpowiedź Patryka (zaakceptowana) jest słuszna: if not a:jest właściwym sposobem na zrobienie tego. Odpowiedź Harleya Holcombe jest słuszna, że jest to w przewodniku po stylu PEP 8. Ale żadna z odpowiedzi nie wyjaśnia, dlaczego dobrym pomysłem jest podążanie za tym idiomem - nawet jeśli osobiście uznasz, że nie jest on wystarczająco wyraźny lub mylący dla użytkowników Ruby lub cokolwiek innego.
Kod Python i społeczność Python mają bardzo silne idiomy. Przestrzeganie tych idiomów ułatwia czytanie kodu każdemu, kto ma doświadczenie w Pythonie. A kiedy naruszasz te idiomy, to silny sygnał.
Prawdą jest, że if not a:nie rozróżnia pustych list None, ani liczbowego 0, pustych krotek, pustych typów kolekcji utworzonych przez użytkownika, ani pustych typów kolekcji, które nie zostały stworzone przez użytkownika, lub tablicy NumPy z jednym elementem działającej jako skalary z falsey wartości itp. Czasami ważne jest, aby o tym wyraźnie mówić. W takim przypadku wiesz, co chcesz wyrazić, więc możesz dokładnie to sprawdzić. Na przykład if not a and a is not None:oznacza „cokolwiek falsey z wyjątkiem Brak”, podczas gdy if len(a) != 0:oznacza „tylko puste sekwencje - a wszystko oprócz sekwencji jest tutaj błędem” i tak dalej. Oprócz testowania dokładnie tego, co chcesz przetestować, oznacza to również dla czytelnika, że ten test jest ważny.
Ale kiedy nie masz nic do wyrażenia, coś innego niż if not a:wprowadza czytelnika w błąd. Sygnalizujesz coś tak ważnego, kiedy tak nie jest. (Można również czyni kod mniej elastyczne, lub wolniej, czy cokolwiek, ale to wszystko mniej ważne.) A jeśli zwykle zmylić czytelnika tak, to kiedy zrobić trzeba dokonać rozróżnienia, to przejdzie niezauważone, ponieważ „płakałeś wilka” w całym kodzie.
Wydaje się, że nikt nie zajął się kwestionowaniem potrzeby przetestowania listy. Ponieważ nie podałeś żadnego dodatkowego kontekstu, mogę sobie wyobrazić, że może nie będziesz musiał tego sprawdzać w pierwszej kolejności, ale nie znasz przetwarzania list w Pythonie.
Twierdziłbym, że najbardziej pythonicznym sposobem jest w ogóle nie sprawdzanie, a po prostu przetworzenie listy. W ten sposób zrobi to dobrze, czy to puste, czy pełne.
a =[]for item in a:<do something with item><rest of code>
Ma to tę zaletę obsługi wszelkich treści , jednocześnie nie wymagając czek specyficzny dla pustki. Jeśli a jest puste, blok zależny nie zostanie wykonany, a tłumacz przejdzie do następnego wiersza.
Jeśli rzeczywiście potrzebujesz sprawdzić tablicę pod kątem pustki, pozostałe odpowiedzi są wystarczające.
Rzecz w tym, że sprawdzenie, czy lista jest pusta, jest dość ważne, przynajmniej dla mnie. Czy zastanawiałeś się, czy w środku jest jakiś skrypt, <rest of code>który mógłby wykorzystać wynik z forpętli? Lub bezpośrednio użyć niektórych wartości w a? Rzeczywiście, jeśli skrypt jest zaprojektowany do działania przy ściśle kontrolowanych danych wejściowych, sprawdzenie może być trochę niepotrzebne. Ale w większości przypadków dane wejściowe są różne, a sprawdzenie jest zwykle lepsze.
Amarth Gûl
Z szacunkiem nie. Uznałem, że ktoś, kto nie wiedział wystarczająco dużo o Pythonie, aby wiedzieć, że „jeśli <lista>:” jest prawidłową odpowiedzią, zapytał, jak sprawdzić pustą listę. Potem zauważam Mnóstwo odpowiedzi, które przedstawiają odmienne opinie, ale żadna nie wydaje się odpowiadać pierwotnej potrzebie. Właśnie to starałem się zrobić z moją odpowiedzią - poproś, aby zbadali potrzebę przed kontynuowaniem. Uważam, że wprost zasugerowałem tyle samo w mojej odpowiedzi.
MrWonderful
@ AmarthGûl - W jaki sposób można uzyskać wyniki z pętli for do skryptu wewnątrz <reszty kodu> do przetworzenia? Może na liście? A może dykt? Jeśli tak, obowiązuje ta sama logika. Nie rozumiem, w jaki sposób zmienne dane wejściowe mogą mieć jakikolwiek wpływ w ramach każdego rozsądnie zaprojektowanego kodu, w którym przetwarzanie pustej listy byłoby złym pomysłem.
MrWonderful
Trochę stary, ale jeśli tylko sprawdzałeś, czy lista jest pusta, w przypadku niepustej listy kod powtarza proces w kółko, gdy OP po prostu szuka operacji sprawdzania. Wyobraź sobie gorszy scenariusz dla tego kodu, gdy n zbliża się do nieskończoności ...
DJK
7
@DJK - Nie, myślę, że nadal go brakuje. Prawdopodobnie chcesz zrobić coś z listą, jeśli ją masz. Co zrobiłbyś inaczej, gdyby był pusty? Wrócić wcześnie? Co jeśli nie jest pusty? przetworzyć to? Chodzi o to, że prawdopodobnie nie musisz sprawdzać pustej listy, po prostu iteruj ją i rób wszystko, co chcesz zrobić z elementami. Jeśli nie ma żadnych elementów, przewracasz się. Jeśli są elementy, przetwarzasz je tak, jak potrzebujesz. Chodzi o to, aby NIE używać przykładu DLA pustego czeku, ale raczej wcale NIE sprawdzać, wystarczy przetworzyć listę.
MrWonderful
66
len()jest operacją O (1) dla list, ciągów, nagrań i zestawów w języku Python. Python wewnętrznie śledzi liczbę elementów w tych kontenerach.
if isinstance(a,(list, some, other, types, i, accept))andnot a:
do_stuff
która została przegłosowana -1. Nie jestem pewien, czy to dlatego, że czytelnicy sprzeciwiali się strategii lub uważali, że odpowiedź nie była pomocna, jak przedstawiono. Udam, że to ten drugi, ponieważ --- cokolwiek liczy się jako „pytoniczne” --- to jest poprawna strategia. O ile już nie wykluczono lub nie jesteś przygotowany do obsługi przypadków, w których ana przykład Falsepotrzebujesz testu bardziej restrykcyjnego niż tylko if not a:. Możesz użyć czegoś takiego:
if isinstance(a, numpy.ndarray)andnot a.size:
do_stuff
elif isinstance(a, collections.Sized)andnot a:
do_stuff
pierwszy test jest odpowiedzią na odpowiedź @ Mike'a powyżej. Trzeci wiersz można również zastąpić:
elif isinstance(a,(list, tuple))andnot a:
jeśli chcesz zaakceptować tylko wystąpienia poszczególnych typów (i ich podtypów) lub za pomocą:
elif isinstance(a,(list, tuple))andnot len(a):
Możesz uciec bez jawnego sprawdzania typu, ale tylko wtedy, gdy otaczający kontekst już cię zapewnia, że ajest to wartość typów, na które jesteś przygotowany, lub jeśli masz pewność, że typy, na które nie jesteś przygotowany, będą do zgłaszania błędów (np. TypeErrorwywołania lenwartości, dla której jest niezdefiniowana), którą jesteś gotowy obsłużyć. Ogólnie rzecz biorąc, konwencje „pytoniczne” wydają się iść w tę ostatnią stronę. Ściśnij go jak kaczkę i pozwól mu podnieść DuckError, jeśli nie wie jak walić. Nadal musisz zastanowić się, jakie przyjmujesz założenia i czy przypadki, do których nie jesteś przygotowany właściwie się zabrać, naprawdę popełniają błąd w odpowiednich miejscach. Tablice Numpy są dobrym przykładem, na którym polegają ślepolen lub typ logiczny może nie robić dokładnie tego, czego oczekujesz.
Bardzo rzadko masz wyczerpującą listę 6 typów, które chcesz zaakceptować i nie być elastycznym dla innych typów. Kiedy potrzebujesz tego rodzaju rzeczy, prawdopodobnie potrzebujesz ABC. W tym przypadku prawdopodobnie byłby to jeden ze standardowych ABC, takich jak collections.abc.Sizedlub collections.abc.Sequence, ale może to być ten, w którym piszesz sam register(list). Jeśli rzeczywiście masz kod, w którym ważne jest odróżnienie pustego od innego falsey, a także odróżnienie list i krotek od innych sekwencji, to jest to poprawne - ale nie sądzę, że masz taki kod.
abarnert
13
Ludzie nie lubią tego, ponieważ w większości przypadków jest to całkowicie pozbawione znaczenia. Python jest językiem kaczym, a ten poziom kodowania obronnego aktywnie to utrudnia. Idea systemu typu Python polega na tym, że wszystko powinno działać tak długo, jak długo obiekt przechodzi w funkcji w sposób, w jaki musi. Wykonując jawne kontrole typów, zmuszasz osobę dzwoniącą do używania określonych typów, co jest sprzeczne z samą ziarnistością języka. Chociaż czasami takie rzeczy są konieczne (wyłączając ciągi traktowane jako sekwencje), takie przypadki są rzadkie i prawie zawsze najlepsze jako czarne listy.
Gareth Latty
1
Jeśli naprawdę chcesz sprawdzić, czy wartość jest dokładnie, []a nie czymś fałszywym innego rodzaju, to na pewno if a == []:jest to wymagane , zamiast zastanawiać się nad isinstance .
RemcoGerlich,
2
==Jednak istnieją pewne automatyczne przymusy . Z czubka mojej głowy nie mogę zidentyfikować żadnego []. [] == ()na przykład zwraca False. Ale na przykład frozenset()==set()powraca True. Warto więc przynajmniej zastanowić się, czy jakiś niepożądany typ może być zmuszony [](lub odwrotnie) podczas działania a == [].
dubiousjim
@RemcoGerlich - isinstance () jest nadal lepszym rozwiązaniem niż tworzenie pustej listy do porównania. Ponadto, jak zauważył inny, operator równości może odwoływać się do niejawnej konwersji niektórych typów, co może być niepożądane. Nie ma powodu, aby kiedykolwiek kodować „a == []”, a kod ten byłby zdecydowanie oznaczony jako usterka w każdej recenzji kodu, w której uczestniczyłem. Używanie odpowiedniego narzędzia dostarczonego przez język nie powinno być uważane za , ale raczej „dobra technika programowania”.
MrWonderful,
29
Z dokumentacji dotyczącej testowania wartości prawdy:
Uwzględniane są wszystkie wartości inne niż wymienione tutaj True
None
False
zera każdego typu liczbowa, na przykład 0, 0.0, 0j.
pustych kolejności, na przykład '', (), [].
dowolne puste mapowanie, na przykład {}.
instancje klas zdefiniowanych przez użytkownika, jeśli klasa definiuje metodę __bool__()lub __len__(), gdy ta metoda zwraca wartość całkowitą zero lub wartość bool False.
Jak widać, pusta lista []jest fałszem , więc robienie tego, co byłoby zrobione z wartością logiczną, brzmi najbardziej efektywnie:
@DJ_Stuffy_K stwierdzam, co w testach jednostkowych pusta lista? Po prostu użyj assert(not myList). Jeśli chcesz również stwierdzić, że obiekt jest list, możesz użyć assertIsInstance().
Sнаđошƒаӽ
24
Oto kilka sposobów sprawdzenia, czy lista jest pusta:
a =[]#the list
1) Dość prosty pythonowy sposób:
ifnot a:print("a is empty")
W Pythonie puste pojemniki, takie jak listy, krotki, zestawy, dykty, zmienne itp. Są postrzegane jako False. Można po prostu traktować listę jako predykat ( zwracającą wartość logiczną ). A Truewartość wskazuje, że nie jest pusta.
2) Bardzo wyraźny sposób: używając, len()aby znaleźć długość i sprawdzić, czy jest ona równa 0:
if len(a)==0:print("a is empty")
3) Lub porównanie z anonimową pustą listą:
if a ==[]:print("a is empty")
4) Innym, ale głupim sposobem jest użycie exceptioni iter():
try:
next(iter(a))# list has elementsexceptStopIteration:print("Error: a is empty")
Będzie to wolniejsze, ponieważ niepotrzebnie tworzysz dodatkową pustą listę.
Carl Meyer,
32
jest to mniej czytelne if not a:i łatwiej się psuje. Proszę nie rób tego.
devsnd
Dobrze jest powiedzieć, że wcześniej () == []jest równa fałszowi. Chociaż podoba mi się to, jak ta implementacja odczytuje if not a:wszystkie przypadki, jeśli zdecydowanie oczekujesz listy, twój przykład powinien wystarczyć.
def list_test (L):if L isNone:print('list is None')elifnot L :print('list is empty')else:print('list has %d elements'% len(L))
list_test(None)
list_test([])
list_test([1,2,3])
Czasami dobrze jest badać Noneosobno i dla pustki, ponieważ są to dwa różne stany. Powyższy kod generuje następujące dane wyjściowe:
list isNone
list is empty
list has 3 elements
Chociaż to nic nie warte Nonejest fałszu. Więc jeśli nie chcesz rozdzielać testu dla None-ness, nie musisz tego robić.
def list_test2 (L):ifnot L :print('list is empty')else:print('list has %d elements'% len(L))
list_test2(None)
list_test2([])
list_test2([1,2,3])
Możliwe, że zgłasza to wyjątek, jeśli anie jest listą i anie ma __len__zaimplementowanej metody . Poleciłbym:if isinstance(obj, list): if len(obj) == 0: print '...'
Sven Krüger
4
@ SvenKrüger nope. Operator andjest leniwy w Pythonie. Nic późniejszego andnie zostanie wykonane, jeśli warunek wcześniejszy andjest False.
ElmoVanKielmo
7
moglibyśmy użyć prostego, jeśli inaczej:
item_list=[]if len(item_list)==0:print("list is empty")else:print("list is not empty")
-1 - Aby uniknąć nieporozumień, nie używaj słów zarezerwowanych dla nazw zmiennych, ponieważ może się to zdarzyć zaskakująco przy następnej próbie wywołania, na przykład „list ()” ... coś w rodzaju „TypeError: obiekt„ list ”to niewymagalne ”czy coś takiego.
MrWonderful
6
Jeśli chcesz sprawdzić, czy lista jest pusta:
l =[]if l:# do your stuff.
Jeśli chcesz sprawdzić, czy wszystkie wartości na liście są puste. Będzie to Truejednak dotyczyło pustej listy:
l =["",False,0,'',[],{},()]if all(bool(x)for x in l):# do your stuff.
Jeśli chcesz używać obu przypadków jednocześnie:
def empty_list(lst):if len(lst)==0:returnFalseelse:return all(bool(x)for x in l)
Za granicą; to tylko pytanie, czy lista jest pusta, a nie czy coś jest pustą iterowalną.
pppery
1
Gdybym nie był zadowolony if a:, to dlatego, że chciałem wyjątku, jeśli anie byłby to jakiś pojemnik. (Bycie iterowalnym pozwala również na iteratory, których nie można z powodzeniem przetestować pod kątem pustki.)
proszę podać więcej wyjaśnień na temat tego, jak to działa bez pisania „jeśli”?
ganeshdeshmukh
3
To nie jest pythoniczny ani kompletny przykład. Ponadto tworzy instancję pustej listy przy każdym napotkaniu. Nie rób tego
MrWonderful
@MrWonderful nie tworzy za każdym razem pustej listy. Po prostu sprawdza, czy istniejąca lista ajest pusta, czy nie.
Tessaracter
@MrWonderful Nie rozumiem, co sprawia, że jestpythonic
Tessaracter
@ganeshdeshmukh, jeśli a==[]go użyjesz , wypisze true na terminalu python, jeśli a jest puste. W przeciwnym razie wydrukuje False. Możesz użyć tego wewnątrz warunku if również jakoif(a==[])
Tessaracter
3
Możesz nawet spróbować użyć bool () w ten sposób
a =[1,2,3];print bool(a);# it will return True
a =[];print bool(a);# it will return False
Uwielbiam ten sposób sprawdzania, czy lista jest pusta, czy nie.
Dla tych (jak ja), którzy nie wiedzieli, bool()konwertuje zmienną Pythona na wartość logiczną, dzięki czemu można przechowywać prawdziwość lub fałsz wartości bez konieczności użycia instrukcji if. Myślę, że jest mniej czytelny niż zwykłe użycie warunku, takiego jak zaakceptowana odpowiedź, ale jestem pewien, że istnieją inne dobre przypadki użycia.
Galen Long
Jest to użyteczne w wyrażeniu i jest bardziej zwięzłe.
qneill,
3
Wystarczy użyć is_empty () lub uczynić funkcję taką jak: -
def is_empty(any_structure):if any_structure:print('Structure is not empty.')returnTrueelse:print('Structure is empty.')returnFalse
Może być używany do dowolnej struktury danych, takiej jak lista, krotki, słownik i wiele innych. Dzięki nim możesz wywoływać go wiele razy za pomocą just is_empty(any_structure).
Nazwa is_emptysugeruje, że coś zwraca. Ale gdyby tak się stało, byłoby to po prostu coś bool(any_structure), czego powinieneś użyć ( kiedybool w ogóle potrzebujesz ).
Davis Herring,
4
Dlaczego chcemy, aby odmiana polegała na booltym, że (także) drukuje komunikaty na standardowe wyjście?
Davis Herring,
@DavisHerring Zawsze zawsze mamy dwa wyjścia, aby wydrukować za pomocą funkcji, inna używa boolzmiennej return . Wybór należy do Ciebie. Piszę oba, abyście mogli wybierać między nimi.
Vineet Jain,
3
Prostym sposobem jest sprawdzenie, czy długość jest równa zero.
To, co mnie tu sprowadziło, to szczególny przypadek użycia: tak naprawdę chciałem, aby funkcja powiedziała mi, czy lista jest pusta, czy nie. Chciałem uniknąć pisania tutaj własnej funkcji lub używania wyrażenia lambda (ponieważ wydawało się, że powinna być dość prosta):
foo = itertools.takewhile(is_not_empty,(f(x)for x in itertools.count(1)))
I oczywiście jest to bardzo naturalny sposób:
foo = itertools.takewhile(bool,(f(x)for x in itertools.count(1)))
Oczywiście nie należy używać boolw if(tj. if bool(L):), Ponieważ jest to dorozumiane. Jednak w przypadkach, gdy „funkcja nie jest pusta” jest wyraźnie potrzebna jako funkcja, booljest najlepszym wyborem.
Aby sprawdzić, czy lista jest pusta, możesz użyć dwóch poniższych sposobów. Pamiętaj jednak, że powinniśmy unikać sposobu jawnego sprawdzania rodzaju sekwencji (jest toless pythonic sposób):
def enquiry(list1):if len(list1)==0:return0else:return1# ––––––––––––––––––––––––––––––––
list1 =[]if enquiry(list1):print("The list isn't empty")else:print("The list is Empty")# Result: "The list is Empty".
Drugi sposób to more pythonic jeden. Ta metoda jest domyślnym sposobem sprawdzania i jest znacznie bardziej preferowana niż poprzednia.
def enquiry(list1):ifnot list1:returnTrueelse:returnFalse# ––––––––––––––––––––––––––––––––
list1 =[]if enquiry(list1):print("The list is Empty")else:print("The list isn't empty")# Result: "The list is Empty"
if a == []
wymusza określony typ (() == []
jestFalse
). tutaj ogólny konsensus wydaje się być taki, że wygrywa pisanie kaczek (w efekcie mówiąc, że__nonzero__
jest to interfejs do testowania pustki docs.python.org/reference/datamodel.html#object.__nonzero__ )Pythoniczny sposób na to jest z przewodnika po stylu PEP 8 (gdzie „ Tak ” oznacza „zalecane”, a „ Nie ” oznacza „niezalecane”):
źródło
seq
ma to być obiekt listy.Wolę to wyraźnie:
W ten sposób jest w 100% jasne, że
li
jest to sekwencja (lista) i chcemy przetestować jej rozmiar. Mój problemif not li: ...
polega na tym, że daje fałszywe wrażenie, żeli
jest zmienną logiczną.źródło
li
to bool, i nie będzie go to obchodzić. Jeśli to ważne, powinieneś dodać komentarz, a nie więcej kodu.None
lub0
zamiast stawiać wyjątek). Tak więc, gdy robisz to bez powodu, to jest mylące, a to oznacza również, że gdy Twój kod ma potrzeby wprowadzania rozróżnienia, rozróżnienie jest niewidoczny, ponieważ masz „Płakał wilk” całej reszty źródła.if bool(len(li) == 0) is True:
?To jest pierwsze trafienie w Google dla „pustej tablicy Pythona” i podobnych zapytań, a inni wydają się uogólniać pytanie poza tylko listami, więc pomyślałem, że dodam zastrzeżenie dla innego rodzaju sekwencji, niż wiele osób może użyć.
Inne metody nie działają dla tablic NumPy
Trzeba uważać na tablice NumPy, ponieważ inne metody, które działają dobrze dla
list
s lub innych standardowych kontenerów, zawodzą w przypadku tablic NumPy. Wyjaśniam dlaczego, ale w skrócie, preferowaną metodą jest użyciesize
.„Pythonowy” sposób nie działa: Część 1
Metoda „pytoniczna” kończy się niepowodzeniem w przypadku tablic NumPy, ponieważ NumPy próbuje rzutować tablicę na tablicę
bool
s iif x
próbuje ocenić wszystkie te wartościbool
naraz dla pewnego rodzaju zagregowanej wartości prawdy. Ale to nie ma sensu, więc otrzymujeszValueError
:Sposób „pythonowy” nie działa: część 2
Ale przynajmniej powyższy przypadek mówi ci, że się nie udało. Jeśli zdarzy ci się, że masz tablicę NumPy z dokładnie jednym elementem,
if
instrukcja będzie „działać” w tym sensie, że nie otrzymasz błędu. Jeśli jednak tym elementem będzie0
(lub0.0
, lubFalse
...),if
instrukcja niepoprawnie spowodujeFalse
:Ale wyraźnie
x
istnieje i nie jest pusty! Ten wynik nie jest tym, czego chciałeś.Korzystanie
len
może dać nieoczekiwane rezultatyNa przykład,
zwraca 1, mimo że tablica zawiera zero elementów.
Sposób numpythonic
Jak wyjaśniono w SciPy FAQ , poprawną metodą we wszystkich przypadkach, w których wiesz, że masz tablicę NumPy, jest użycie
if x.size
:Jeśli nie masz pewności, czy może to być
list
tablica NumPy, czy coś innego, możesz połączyć to podejście z odpowiedzią podaną przez @dubiousjim, aby upewnić się, że dla każdego typu zastosowano odpowiedni test. Niezbyt „pythoniczny”, ale okazuje się, że NumPy celowo złamał pythonicity przynajmniej w tym sensie.Jeśli trzeba zrobić więcej niż po prostu sprawdzić, czy wkład jest pusty, a używasz innego NumPy takich jak operacje indeksowania lub matematycznych, to chyba bardziej wydajne (a na pewno bardziej powszechne), aby wymusić wejście do być tablicą NumPy. Jest kilka fajnych funkcji umożliwiających szybkie wykonanie tego - co najważniejsze
numpy.asarray
. To pobiera dane wejściowe, nie robi nic, jeśli jest już tablicą, lub zawija dane wejściowe w tablicę, jeśli jest to lista, krotka itp., I opcjonalnie konwertuje ją na wybranądtype
. Jest więc bardzo szybki, gdy tylko jest to możliwe, i zapewnia, że po prostu przyjmiesz, że dane wejściowe to tablica NumPy. Zwykle używamy nawet tej samej nazwy, ponieważ konwersja na tablicę nie spowoduje, że znajdzie się poza bieżącym zakresem :Sprawi to, że
x.size
czek zadziała we wszystkich przypadkach, które widzę na tej stronie.źródło
numpy
-numpy
jest biblioteką z bardzo konkretnym przypadkiem użycia i ma inną „naturalną” definicję prawdziwości tablicy Standard Python dla kontenerów. To ma sens, aby zoptymalizować dla tego przypadku, w sposób, którypathlib
używa/
do łączenia ścieżek zamiast+
- to nietypowe, ale ma sens w kontekście.if x
ilen(x)
idiomów - a czasami to złamanie może być bardzo trudne do wykrycia i debugowania.Krótka odpowiedź:
Umieść listę w kontekście logicznym (na przykład za pomocą instrukcji
if
lubwhile
). Będzie sprawdzał,False
czy jest pusty, iTrue
inaczej. Na przykład:PEP 8
PEP 8 , oficjalny przewodnik po języku Python dla kodu Python w standardowej bibliotece Pythona, zapewnia:
Powinniśmy oczekiwać, że standardowy kod biblioteki powinien być tak wydajny i poprawny, jak to możliwe. Ale dlaczego tak jest i dlaczego potrzebujemy tych wskazówek?
Wyjaśnienie
Często widzę taki kod od doświadczonych programistów początkujących w Pythonie:
A użytkownicy leniwych języków mogą ulec pokusie:
Są poprawne w swoich odpowiednich językach. Jest to nawet semantycznie poprawne w Pythonie.
Ale uważamy to za nie-Pythonic, ponieważ Python obsługuje tę semantykę bezpośrednio w interfejsie obiektu listy za pomocą logicznego koercji.
Z dokumentów (i zwróć uwagę na włączenie pustej listy
[]
):Oraz dokumentacja modelu danych:
i
Zamiast tego:
albo to:
Zrób to:
Robienie tego, co Pythonic zwykle się opłaca:
Czy to się opłaca? (Pamiętaj, że krótszy czas na wykonanie równoważnej operacji jest lepszy :)
Dla skali, oto koszt wywołania funkcji oraz zbudowania i zwrócenia pustej listy, którą możesz odjąć od kosztów kontroli pustki użytych powyżej:
Widzimy, że albo sprawdzanie na długości za pomocą funkcji wbudowanej
len
w porównaniu do0
lub sprawdzenie przed pustym liście jest znacznie mniej wydajnych niż przy użyciu składni wbudowanego języka jako udokumentowane.Dlaczego?
Do
len(a) == 0
kontroli:Najpierw Python musi sprawdzić globale, aby zobaczyć, czy
len
jest zacieniony.Następnie musi wywołać funkcję, załadować
0
i wykonać porównanie równości w Pythonie (zamiast z C):Aby to
[] == []
zrobić, musi zbudować niepotrzebną listę, a następnie ponownie wykonać operację porównania na maszynie wirtualnej Pythona (w przeciwieństwie do C)Sposób „Pythonic” jest znacznie prostszym i szybszym sprawdzaniem, ponieważ długość listy jest buforowana w nagłówku instancji obiektu:
Dowody ze źródła C i dokumentacji
Ze źródła c w pliku Include / listobject.h :
Odpowiedź na komentarze:
Magia IPython
%timeit
nie jest tutaj całkowicie bezużyteczna:Widzimy tutaj trochę liniowego kosztu każdego dodatkowego
not
. Chcemy, aby koszty, ceteris paribus , to znaczy wszystkie inne były równe - gdzie wszystko inne jest zminimalizowane w największym możliwym stopniu:Teraz spójrzmy na przypadek niepustej listy:
Widzimy tutaj, że nie ma większego znaczenia, czy przekazujesz rzeczywiste
bool
sprawdzenie stanu, czy samą listę, a jeśli tak, to podanie listy, tak jak jest, jest szybsze.Python jest napisany w C; używa swojej logiki na poziomie C. Wszystko, co napiszesz w Pythonie, będzie wolniejsze. I prawdopodobnie będzie to rząd wielkości wolniejszy, chyba że użyjesz mechanizmów wbudowanych bezpośrednio w Pythona.
źródło
l=[]
czym%timeit len(l) != 0
90,6 NS NS ± 8,3,%timeit l != []
55,6 ± 3,09 ns,%timeit not not l
38,5 ± 0,372 ns. Ale nie ma mowy, aby ktokolwiek mógł się cieszyćnot not l
pomimo potrójnej prędkości. To wygląda niedorzecznie. Ale prędkość wygrywaif l:
jest po prostu wystarczający, ale zaskakująco%timeit bool(l)
daje 101 ns ± 2,64 ns. Ciekawe, że bez tej kary nie można zmusić do buntu.%timeit l
jest bezużyteczny, ponieważ nie nastąpiłaby konwersja.Pusta lista sama w sobie jest uważana za fałszywą podczas testowania prawdziwej wartości (patrz dokumentacja Pythona ):
@Daren Thomas
Twój duckCollection powinny wdrożyć
__nonzero__
lub__len__
więc jeśli: będzie działać bez problemów.źródło
[] == False
oceni się na Falsebool()
.bool([]) == False
oceniTrue
zgodnie z oczekiwaniami.Odpowiedź Patryka (zaakceptowana) jest słuszna:
if not a:
jest właściwym sposobem na zrobienie tego. Odpowiedź Harleya Holcombe jest słuszna, że jest to w przewodniku po stylu PEP 8. Ale żadna z odpowiedzi nie wyjaśnia, dlaczego dobrym pomysłem jest podążanie za tym idiomem - nawet jeśli osobiście uznasz, że nie jest on wystarczająco wyraźny lub mylący dla użytkowników Ruby lub cokolwiek innego.Kod Python i społeczność Python mają bardzo silne idiomy. Przestrzeganie tych idiomów ułatwia czytanie kodu każdemu, kto ma doświadczenie w Pythonie. A kiedy naruszasz te idiomy, to silny sygnał.
Prawdą jest, że
if not a:
nie rozróżnia pustych listNone
, ani liczbowego 0, pustych krotek, pustych typów kolekcji utworzonych przez użytkownika, ani pustych typów kolekcji, które nie zostały stworzone przez użytkownika, lub tablicy NumPy z jednym elementem działającej jako skalary z falsey wartości itp. Czasami ważne jest, aby o tym wyraźnie mówić. W takim przypadku wiesz, co chcesz wyrazić, więc możesz dokładnie to sprawdzić. Na przykładif not a and a is not None:
oznacza „cokolwiek falsey z wyjątkiem Brak”, podczas gdyif len(a) != 0:
oznacza „tylko puste sekwencje - a wszystko oprócz sekwencji jest tutaj błędem” i tak dalej. Oprócz testowania dokładnie tego, co chcesz przetestować, oznacza to również dla czytelnika, że ten test jest ważny.Ale kiedy nie masz nic do wyrażenia, coś innego niż
if not a:
wprowadza czytelnika w błąd. Sygnalizujesz coś tak ważnego, kiedy tak nie jest. (Można również czyni kod mniej elastyczne, lub wolniej, czy cokolwiek, ale to wszystko mniej ważne.) A jeśli zwykle zmylić czytelnika tak, to kiedy zrobić trzeba dokonać rozróżnienia, to przejdzie niezauważone, ponieważ „płakałeś wilka” w całym kodzie.źródło
Po co w ogóle sprawdzać?
Wydaje się, że nikt nie zajął się kwestionowaniem potrzeby przetestowania listy. Ponieważ nie podałeś żadnego dodatkowego kontekstu, mogę sobie wyobrazić, że może nie będziesz musiał tego sprawdzać w pierwszej kolejności, ale nie znasz przetwarzania list w Pythonie.
Twierdziłbym, że najbardziej pythonicznym sposobem jest w ogóle nie sprawdzanie, a po prostu przetworzenie listy. W ten sposób zrobi to dobrze, czy to puste, czy pełne.
Ma to tę zaletę obsługi wszelkich treści , jednocześnie nie wymagając czek specyficzny dla pustki. Jeśli a jest puste, blok zależny nie zostanie wykonany, a tłumacz przejdzie do następnego wiersza.
Jeśli rzeczywiście potrzebujesz sprawdzić tablicę pod kątem pustki, pozostałe odpowiedzi są wystarczające.
źródło
<rest of code>
który mógłby wykorzystać wynik zfor
pętli? Lub bezpośrednio użyć niektórych wartości wa
? Rzeczywiście, jeśli skrypt jest zaprojektowany do działania przy ściśle kontrolowanych danych wejściowych, sprawdzenie może być trochę niepotrzebne. Ale w większości przypadków dane wejściowe są różne, a sprawdzenie jest zwykle lepsze.len()
jest operacją O (1) dla list, ciągów, nagrań i zestawów w języku Python. Python wewnętrznie śledzi liczbę elementów w tych kontenerach.JavaScript ma podobne pojęcie „prawda / fałsz” .
źródło
Napisałem:
która została przegłosowana -1. Nie jestem pewien, czy to dlatego, że czytelnicy sprzeciwiali się strategii lub uważali, że odpowiedź nie była pomocna, jak przedstawiono. Udam, że to ten drugi, ponieważ --- cokolwiek liczy się jako „pytoniczne” --- to jest poprawna strategia. O ile już nie wykluczono lub nie jesteś przygotowany do obsługi przypadków, w których
a
na przykładFalse
potrzebujesz testu bardziej restrykcyjnego niż tylkoif not a:
. Możesz użyć czegoś takiego:pierwszy test jest odpowiedzią na odpowiedź @ Mike'a powyżej. Trzeci wiersz można również zastąpić:
jeśli chcesz zaakceptować tylko wystąpienia poszczególnych typów (i ich podtypów) lub za pomocą:
Możesz uciec bez jawnego sprawdzania typu, ale tylko wtedy, gdy otaczający kontekst już cię zapewnia, że
a
jest to wartość typów, na które jesteś przygotowany, lub jeśli masz pewność, że typy, na które nie jesteś przygotowany, będą do zgłaszania błędów (np.TypeError
wywołanialen
wartości, dla której jest niezdefiniowana), którą jesteś gotowy obsłużyć. Ogólnie rzecz biorąc, konwencje „pytoniczne” wydają się iść w tę ostatnią stronę. Ściśnij go jak kaczkę i pozwól mu podnieść DuckError, jeśli nie wie jak walić. Nadal musisz zastanowić się, jakie przyjmujesz założenia i czy przypadki, do których nie jesteś przygotowany właściwie się zabrać, naprawdę popełniają błąd w odpowiednich miejscach. Tablice Numpy są dobrym przykładem, na którym polegają ślepolen
lub typ logiczny może nie robić dokładnie tego, czego oczekujesz.źródło
collections.abc.Sized
lubcollections.abc.Sequence
, ale może to być ten, w którym piszesz samregister(list)
. Jeśli rzeczywiście masz kod, w którym ważne jest odróżnienie pustego od innego falsey, a także odróżnienie list i krotek od innych sekwencji, to jest to poprawne - ale nie sądzę, że masz taki kod.[]
a nie czymś fałszywym innego rodzaju, to na pewnoif a == []:
jest to wymagane , zamiast zastanawiać się nad isinstance .==
Jednak istnieją pewne automatyczne przymusy . Z czubka mojej głowy nie mogę zidentyfikować żadnego[]
.[] == ()
na przykład zwracaFalse
. Ale na przykładfrozenset()==set()
powracaTrue
. Warto więc przynajmniej zastanowić się, czy jakiś niepożądany typ może być zmuszony[]
(lub odwrotnie) podczas działaniaa == []
.Z dokumentacji dotyczącej testowania wartości prawdy:
Uwzględniane są wszystkie wartości inne niż wymienione tutaj
True
None
False
0
,0.0
,0j
.''
,()
,[]
.{}
.__bool__()
lub__len__()
, gdy ta metoda zwraca wartość całkowitą zero lub wartość boolFalse
.Jak widać, pusta lista
[]
jest fałszem , więc robienie tego, co byłoby zrobione z wartością logiczną, brzmi najbardziej efektywnie:źródło
assert(not myList)
. Jeśli chcesz również stwierdzić, że obiekt jestlist
, możesz użyćassertIsInstance()
.Oto kilka sposobów sprawdzenia, czy lista jest pusta:
1) Dość prosty pythonowy sposób:
W Pythonie puste pojemniki, takie jak listy, krotki, zestawy, dykty, zmienne itp. Są postrzegane jako
False
. Można po prostu traktować listę jako predykat ( zwracającą wartość logiczną ). ATrue
wartość wskazuje, że nie jest pusta.2) Bardzo wyraźny sposób: używając,
len()
aby znaleźć długość i sprawdzić, czy jest ona równa0
:3) Lub porównanie z anonimową pustą listą:
4) Innym, ale głupim sposobem jest użycie
exception
iiter()
:źródło
Wolę następujące:
źródło
if not a:
i łatwiej się psuje. Proszę nie rób tego.() == []
jest równa fałszowi. Chociaż podoba mi się to, jak ta implementacja odczytujeif not a:
wszystkie przypadki, jeśli zdecydowanie oczekujesz listy, twój przykład powinien wystarczyć.Metoda 1 (preferowana):
Metoda 2:
Metoda 3:
źródło
Czasami dobrze jest badać
None
osobno i dla pustki, ponieważ są to dwa różne stany. Powyższy kod generuje następujące dane wyjściowe:Chociaż to nic nie warte
None
jest fałszu. Więc jeśli nie chcesz rozdzielać testu dlaNone
-ness, nie musisz tego robić.produkuje oczekiwany
źródło
Podano wiele odpowiedzi, a wiele z nich jest całkiem dobrych. Chciałem tylko dodać tę czek
przejdzie również
None
i inne rodzaje pustych struktur. Jeśli naprawdę chcesz sprawdzić pustą listę, możesz to zrobić:źródło
a
nie jest listą ia
nie ma__len__
zaimplementowanej metody . Poleciłbym:if isinstance(obj, list): if len(obj) == 0: print '...'
and
jest leniwy w Pythonie. Nic późniejszegoand
nie zostanie wykonane, jeśli warunek wcześniejszyand
jest False.moglibyśmy użyć prostego, jeśli inaczej:
źródło
Jeśli chcesz sprawdzić, czy lista jest pusta:
Jeśli chcesz sprawdzić, czy wszystkie wartości na liście są puste. Będzie to
True
jednak dotyczyło pustej listy:Jeśli chcesz używać obu przypadków jednocześnie:
Teraz możesz użyć:
źródło
Zainspirowany rozwiązaniem @ dubiousjim, proponuję zastosować dodatkowe ogólne sprawdzenie, czy jest to coś iterowalnego
Uwaga: ciąg uważa się za iterowalny. - Dodaj
and not isinstance(a,(str,unicode))
jeśli chcesz, aby pusty ciąg został wykluczonyTest:
źródło
if a:
, to dlatego, że chciałem wyjątku, jeślia
nie byłby to jakiś pojemnik. (Bycie iterowalnym pozwala również na iteratory, których nie można z powodzeniem przetestować pod kątem pustki.)trochę bardziej praktyczne:
i wersja shertest:
źródło
Od Python3 możesz używać
aby sprawdzić, czy lista jest pusta
EDYCJA: Działa to również z python2.7.
Nie jestem pewien, dlaczego jest tak wiele skomplikowanych odpowiedzi. To całkiem jasne i proste
źródło
a
jest pusta, czy nie.pythonic
a==[]
go użyjesz , wypisze true na terminalu python, jeśli a jest puste. W przeciwnym razie wydrukuje False. Możesz użyć tego wewnątrz warunku if również jakoif(a==[])
Możesz nawet spróbować użyć bool () w ten sposób
Uwielbiam ten sposób sprawdzania, czy lista jest pusta, czy nie.
Bardzo przydatny i użyteczny.
źródło
bool()
konwertuje zmienną Pythona na wartość logiczną, dzięki czemu można przechowywać prawdziwość lub fałsz wartości bez konieczności użycia instrukcji if. Myślę, że jest mniej czytelny niż zwykłe użycie warunku, takiego jak zaakceptowana odpowiedź, ale jestem pewien, że istnieją inne dobre przypadki użycia.Wystarczy użyć is_empty () lub uczynić funkcję taką jak: -
Może być używany do dowolnej struktury danych, takiej jak lista, krotki, słownik i wiele innych. Dzięki nim możesz wywoływać go wiele razy za pomocą just
is_empty(any_structure)
.źródło
is_empty
sugeruje, że coś zwraca. Ale gdyby tak się stało, byłoby to po prostu cośbool(any_structure)
, czego powinieneś użyć ( kiedybool
w ogóle potrzebujesz ).bool
tym, że (także) drukuje komunikaty na standardowe wyjście?bool
zmiennej return . Wybór należy do Ciebie. Piszę oba, abyście mogli wybierać między nimi.Prostym sposobem jest sprawdzenie, czy długość jest równa zero.
źródło
Prawdą jest,
False
że pusta lista jest prawdą, podczas gdy dla niepustej listy jest to prawdaTrue
.źródło
To, co mnie tu sprowadziło, to szczególny przypadek użycia: tak naprawdę chciałem, aby funkcja powiedziała mi, czy lista jest pusta, czy nie. Chciałem uniknąć pisania tutaj własnej funkcji lub używania wyrażenia lambda (ponieważ wydawało się, że powinna być dość prosta):
I oczywiście jest to bardzo naturalny sposób:
Oczywiście nie należy używać
bool
wif
(tj.if bool(L):
), Ponieważ jest to dorozumiane. Jednak w przypadkach, gdy „funkcja nie jest pusta” jest wyraźnie potrzebna jako funkcja,bool
jest najlepszym wyborem.źródło
Mam nadzieję że to pomoże.
źródło