Jak sprawdzić, czy ciąg jest pusty?


1414

Czy Python ma coś w rodzaju pustej zmiennej łańcuchowej, w której możesz:

if myString == string.empty:

Niezależnie od tego, jaki jest najbardziej elegancki sposób sprawdzania pustych wartości ciągu? Za ""każdym razem znajduję stałe kodowanie, aby sprawdzić pusty ciąg znaków nie tak dobry.


2
Jak ""nie jest tak dobrze?
NoName

Odpowiedzi:


2110

Puste ciągi znaków są „fałszowane”, co oznacza, że ​​są uważane za fałszywe w kontekście logicznym, więc możesz to po prostu zrobić:

if not myString:

Jest to preferowany sposób, jeśli wiesz, że twoja zmienna jest łańcuchem. Jeśli twoja zmienna może być również innego typu, powinieneś użyć myString == "". Zobacz dokumentację dotyczącą testowania wartości prawdy, aby znaleźć inne wartości, które są fałszywe w kontekście boolowskim.


183
Bądź ostrożny, ponieważ wiele innych rzeczy jest również fałszywych.
Ignacio Vazquez-Abrams,

9
Nigdy wcześniej nie słyszałem o falsy. Czy to oznacza, że ​​zwraca false?
Joan Venge

41
@Joan: Ocenia się jako fałsz w kontekście logicznym.
Ignacio Vazquez-Abrams,

54
PO chce wiedzieć, czy zmienna jest pusty ciąg znaków, ale także wprowadzić if not myString:blok jeśli myStringbyły None, 0, Falseitd., Więc jeśli nie jesteś pewien, jakiego rodzaju myStringjest, należy użyć if myString == "":w celu ustalenia, czy jest pusty ciąg znaków, w przeciwieństwie do jakaś inna wartość fałsz.
Andrew Clark,

15
@AndrewClark, w takim przypadku zamiast łańcucha if myString == ...wyrażeń moglibyśmy użyć if myString in (None, '')lub na @Bartek,if myString in (None, '') or not myString.strip()
Stew

411

Z PEP 8 w sekcji „Zalecenia dotyczące programowania” :

W przypadku sekwencji (ciągów, list, krotek) użyj faktu, że puste sekwencje są fałszywe.

Więc powinieneś użyć:

if not some_string:

lub:

if some_string:

Aby wyjaśnić, sekwencje są oceniane w Falselub Truew kontekście logicznym, jeśli są puste, czy nie. Są nie równa się Falselub True.


24
Świetnie, że zamieściłeś odniesienia do PEP!
Felix

3
PS: W obronie PEP można argumentować, że powiedzenie „ x jest fałszem ” (małe fałsz ) oznacza już to, a nie znaczenie x == False. Ale wyjaśnienie IMHO jest nadal mile widziane, biorąc pod uwagę grupę docelową.
MestreLion

232

Najbardziej eleganckim sposobem byłoby prawdopodobnie sprawdzenie, czy jest to prawda czy fałsz, np .:

if not my_string:

Możesz jednak usunąć białe znaki, ponieważ:

 >>> bool("")
 False
 >>> bool("   ")
 True
 >>> bool("   ".strip())
 False

Prawdopodobnie powinieneś być w tym nieco bardziej wyraźny, chyba że wiesz na pewno, że ten łańcuch przeszedł pewną walidację i jest łańcuchem, który można przetestować w ten sposób.


87

Chciałbym przetestować jedność przed rozbiórką. Wykorzystałbym również fakt, że puste ciągi znaków są fałszywe (lub Falsy). To podejście jest podobne do StringUtils.isBlank Apache lub Strings.isNullOrEmpty Guava

Oto, czego użyłbym do przetestowania, jeśli łańcuch ma wartość Brak LUB Pusty LUB Pusty:

def isBlank (myString):
    if myString and myString.strip():
        #myString is not None AND myString is not empty or blank
        return False
    #myString is None OR myString is empty or blank
    return True

I dokładnie odwrotnie niż w przypadku testu, jeśli ciąg znaków nie jest Brak NOR Pusty NOR Pusty:

def isNotBlank (myString):
    if myString and myString.strip():
        #myString is not None AND myString is not empty or blank
        return True
    #myString is None OR myString is empty or blank
    return False

Bardziej zwięzłe formy powyższego kodu:

def isBlank (myString):
    return not (myString and myString.strip())

def isNotBlank (myString):
    return bool(myString and myString.strip())

dlaczego nie if mystring and not mystring.strip()?
Migol

1
Czym się różni string and not string.isspace()?
Andrea Corbellini,

7
Bardziej zwięzłe dla tych, którzy dbają o takie rzeczy: def isBlank(s): return not (s and s.strip())i def isNotBlank(s): return s and s.strip().
Carl

48

Kiedyś napisałem coś podobnego do odpowiedzi Bartka i inspirowałem się javascript:

def is_not_blank(s):
    return bool(s and s.strip())

Test:

print is_not_blank("")    # False
print is_not_blank("   ") # False
print is_not_blank("ok")  # True
print is_not_blank(None)  # False

Dlaczego nie tylkoreturn bool(s.strip())
anilbey

1
AttributeError: 'NoneType' object has no attribute 'strip'
sklepienie

28

Jedyny naprawdę solidny sposób to zrobić:

if "".__eq__(myString):

Wszystkie inne rozwiązania mają możliwe problemy i przypadki brzegowe, w których sprawdzenie może się nie powieść.

len(myString)==0może zawieść, jeśli myStringjest obiektem klasy, która dziedziczy stri zastępuje __len__()metodę.

Podobnie myString == ""i myString.__eq__("")może zawieść, jeśli myStringzastąpi __eq__()i __ne__().

Z jakiegoś powodu "" == myStringdaje się również zwieść, jeśli myStringzastąpi __eq__().

myString is ""i "" is myStringsą równoważne. Oba zawiodą, jeśli w myStringrzeczywistości nie jest łańcuchem, ale podklasą łańcucha (oba zwrócą False). Ponadto, ponieważ są to kontrole tożsamości, jedynym powodem, dla którego działają, jest to, że Python używa String Pooling (zwanego również internacjonalizacją ciągu), który korzysta z tej samej instancji ciągu, jeśli jest internowany (patrz tutaj: Dlaczego porównywanie ciągów za pomocą albo '= = ”lub„ is ”czasami dają inny wynik? ). I ""jest internowany od samego początku w CPython

Dużym problemem związanym z kontrolą tożsamości jest to, że internowanie ciągów jest (o ile mogłem znaleźć) tym, że nie jest ustandaryzowane, które ciągi są internowane. Oznacza to, że teoretycznie ""nie jest konieczne internowanie i zależy to od implementacji.

Jedynym sposobem na osiągnięcie tego, że tak naprawdę nie da się oszukać jedną wspomniałem na początku: "".__eq__(myString). Ponieważ to jawnie wywołuje __eq__()metodę pustego ciągu, nie można go oszukać przez przesłanianie jakichkolwiek metod w myString i solidnie działa z podklasamistr .

Również poleganie na falsyniczności łańcucha może nie działać, jeśli obiekt go przesłoni __bool__() metodę.

Jest to nie tylko praca teoretyczna, ale może być istotna w rzeczywistym użyciu, ponieważ widziałem podklasy bibliotek i bibliotek strprzed użyciemmyString is "" może zwrócić tam niepoprawne dane wyjściowe.

Również porównywanie ciągów za pomocą is ogólnie jest dość złą pułapką, ponieważ czasami działa poprawnie, ale nie w innym czasie, ponieważ pula ciągów znaków jest dość dziwna.

To powiedziawszy, w większości przypadków wszystkie wymienione rozwiązania będą działać poprawnie. Ten post jest głównie pracą akademicką.


2
@simpleuser masz oczywiście rację. W prawdziwym świecie można używać fałszowania łańcucha lub porównywać go z pustym łańcuchem. Ta odpowiedź jest celowo nadmierna.
Dakkaron

naprawdę, użyj eq_ ?
łódka

działa świetnie, dziękuję!
eugene.polschikov

14

Przetestuj pusty lub pusty ciąg (krócej):

if myString.strip():
    print("it's not an empty or blank string")
else:
    print("it's an empty or blank string")

7
Jeśli myString = Nonespowoduje wyjątek. Lepsze wykorzystanie @ skarbca odpowiedź
Dominik

9

Jeśli chcesz rozróżnić puste i puste ciągi, sugerowałbym użycie if len(string), w przeciwnym razie sugerowałbym użycie if stringtak, jak powiedzieli inni. Zastrzeżenie dotyczące ciągów pełnych białych znaków ma jednak zastosowanie, więc nie zapomnij o tym strip.


Nie wiem, dlaczego chcesz unikać używania „”, chyba że w jakiś sposób wpływa to na wydajność, ale wolę twoją odpowiedź od tej z milionami głosów pozytywnych, ponieważ jest to mniej mylące. Chciałem jednak zaznaczyć, że pusta lista jest również fałszywa.
Brōtsyorfuzthrāx

6

if stringname:daje, falsegdy ciąg jest pusty. Myślę, że to nie może być prostsze niż to.


6
a = ''
b = '   '
a.isspace() -> False
b.isspace() -> True

1
Naprawdę nie rozumiem, co zyskuje to rozwiązanie. Pytanie dotyczy sprawdzenia, czy ciąg znaków jest pusty. Jeśli ustawisz a='a', otrzymasz a.isspace() -> False, ale ana tym koncie nie będzie pusty ciąg.
Adrian Keister

6

Za każdym razem uważam, że kodowanie „sic” nie jest tak dobre.

Podejście do czystego kodu

Robienie tego: foo == ""jest bardzo złą praktyką. ""jest magiczną wartością. Nigdy nie powinieneś sprawdzać wartości magicznych (bardziej znanych jako liczby magiczne) )

Co powinieneś zrobić, to porównać do opisowej nazwy zmiennej.

Opisowe nazwy zmiennych

Ktoś może pomyśleć, że „empty_string” to opisowa nazwa zmiennej. To nie jest .

Zanim pójdziesz i zrobisz empty_string = "" pomyślisz, że masz świetną nazwę zmiennej do porównania. Nie to znaczy „nazwa zmiennej opisowej”.

Dobra nazwa zmiennej opisowej oparta jest na jej kontekście. Trzeba myśleć o tym, co pusty łańcuch jest .

  • Skąd to pochodzi.
  • Dlaczego tam jest
  • Dlaczego musisz to sprawdzić?

Prosty przykład pola formularza

Budujesz formularz, w którym użytkownik może wprowadzać wartości. Chcesz sprawdzić, czy użytkownik coś napisał, czy nie.

Dobra nazwa zmiennej może być not_filled_in

Dzięki temu kod jest bardzo czytelny

if formfields.name == not_filled_in:
    raise ValueError("We need your name")

Dokładny przykład analizy CSV

Analizujesz pliki CSV i chcesz, aby pusty ciąg był analizowany jako None

(Ponieważ CSV jest w całości oparty na tekście, nie może reprezentować None bez użycia wstępnie zdefiniowanych słów kluczowych)

Dobra nazwa zmiennej może być CSV_NONE

Ułatwia to zmianę i dostosowanie kodu, jeśli masz nowy plik CSV, który reprezentuje Noneinny ciąg niż""

if csvfield == CSV_NONE:
    csvfield = None

Nie ma pytań, czy ten fragment kodu jest poprawny. Jest całkiem jasne, że robi to, co powinien.

Porównaj to z

if csvfield == EMPTY_STRING:
    csvfield = None

Pierwsze pytanie brzmi: dlaczego pusty ciąg zasługuje na specjalne traktowanie?

Oznaczałoby to przyszłym programistom, że pusty ciąg powinien być zawsze uważany za None .

Jest tak, ponieważ łączy logikę biznesową (jaka powinna być wartość CSV None ) z implementacją kodu (z czym tak naprawdę porównujemy)

Trzeba między nimi rozdzielić obawy .


1
Czy naprawdę trzeba zadać sobie tyle trudu, aby uniknąć „”? Co w kontekście porównania może oznaczać pusty ciąg?

Jak piszę w mojej odpowiedzi, CSV nie może reprezentować wartości null bez użycia łańcucha. Jeśli nie masz kontekstu, gratulacje! Większość kodu nie jest.
firelynx

2
mówisz, że „not_filled_in” jest bardziej opisowe niż „empty_string”? Mówię, że jesteś na haju.
Tuncay Göncüoğlu

@ TuncayGöncüoğlu „Pusty ciąg” nie opisuje tego, co sprawdza instrukcja if.
firelynx

5
Nie zgodziłbym się z tą odpowiedzią. Liczby magiczne są złe, to ma sens. Ogólnie wartości magiczne. Ale ""nie jest magiczną wartością, taką samą True, Falseani Nonenie jest magiczną wartością.
Dakkaron

5

Co powiesz na to? Być może nie jest to „najbardziej elegancki”, ale wydaje się dość kompletny i jasny:

if (s is None) or (str(s).strip()==""): // STRING s IS "EMPTY"...

W większości przypadków ciąg zawierający spacje nie jest „pusty”.
Chris Johnson

Zakładam, że masz na myśli tylko białą przestrzeń? Masz na myśli moje użycie strip ()? W większości przypadków jest pusty! Absurdalnie powszechne jest łączenie czegoś takiego jak s.trim (). IsEmpty ()
BuvinJ

Hej @Chris Johnson, czy widziałeś, że NAJCZĘŚCIEJ z odpowiedzi tutaj również używa strip ()? Czy głosowałeś na nas wszystkich, czy tylko na mnie?
BuvinJ

4

Odpowiadanie na @ 1290. Przepraszamy, nie ma możliwości sformatowania bloków w komentarzach. NoneWartość nie jest pusty ciąg znaków w Pythonie, i nie jest (ze spacjami). Odpowiedź z Andrew Clark jest prawidłowa: if not myString. Odpowiedź @rouble jest specyficzna dla aplikacji i nie odpowiada na pytanie PO. Wpadniesz w kłopoty, jeśli przyjmiesz osobliwą definicję „pustego” ciągu. W szczególności, średnia zachowanie jest, że str(None)produkuje'None' niepustego łańcucha.

Jeśli jednak musisz traktować Nonei (spacje) jako „puste” ciągi, oto lepszy sposób:

class weirdstr(str):
    def __new__(cls, content):
        return str.__new__(cls, content if content is not None else '')
    def __nonzero__(self):
        return bool(self.strip())

Przykłady:

>>> normal = weirdstr('word')
>>> print normal, bool(normal)
word True

>>> spaces = weirdstr('   ')
>>> print spaces, bool(spaces)
    False

>>> blank = weirdstr('')
>>> print blank, bool(blank)
 False

>>> none = weirdstr(None)
>>> print none, bool(none)
 False

>>> if not spaces:
...     print 'This is a so-called blank string'
... 
This is a so-called blank string

Spełnia wymagania @rouble, nie przerywając oczekiwanego boolzachowania ciągów.


python -c "if (str(None) == 'None'): print ('OMG, WHY ??')"
Yordan Georgiev

3

Uważam to za eleganckie, ponieważ upewnia się, że jest to sznurek i sprawdza jego długość:

def empty(mystring):
    assert isinstance(mystring, str)
    if len(mystring) == 0:
        return True
    else:
        return False

Ostrzeżenie, aserty mają służyć jako narzędzie do debugowania i zoptymalizować je, jeśli przejdziesz -Oflagę lub ustawisz PYTHONOPTIMIZEzmienną env.
SilentVoid,

2

Innym łatwym sposobem może być zdefiniowanie prostej funkcji:

def isStringEmpty(inputString):
    if len(inputString) == 0:
        return True
    else:
        return False

3
odpowiedź z kardamonu jest bardziej kompletna, jeśli chcemy sprawdzić, czy dane wejściowe są ciągiem znaków, czy nie
tanzil 11.04.19

1
not str(myString)

To wyrażenie ma wartość True dla ciągów, które są puste. Niepuste łańcuchy, Żaden i obiekty nie łańcuchowe będą generować False, z zastrzeżeniem, że obiekty mogą nadpisać __str__, aby udaremnić tę logikę, zwracając wartość fałszowania.




0

Gdy czytasz plik po liniach i chcesz ustalić, która linia jest pusta, upewnij się, że użyjesz .strip(), ponieważ w wierszu „pustym” jest nowy znak linii:

lines = open("my_file.log", "r").readlines()

for line in lines:
    if not line.strip():
        continue

    # your code for non-empty lines


0

Jeśli tylko użyjesz

not var1 

nie można odróżnić zmiennej boolean Falseod pustego łańcucha '':

var1 = ''
not var1
> True

var1 = False
not var1
> True

Jeśli jednak dodasz prosty warunek do skryptu, różnica będzie następująca:

var1  = False
not var1 and var1 != ''
> True

var1 = ''
not var1 and var1 != ''
> False

0

Jeśli jest to przydatne dla kogoś, oto szybka funkcja, którą zbudowałem, aby zastąpić puste ciągi znakami N / A na listach list (python 2).

y = [["1","2",""],["1","4",""]]

def replace_blank_strings_in_lists_of_lists(list_of_lists):
    new_list = []
    for one_list in list_of_lists:
        new_one_list = []
        for element in one_list:
            if element:
                new_one_list.append(element)
            else:
                new_one_list.append("N/A")
        new_list.append(new_one_list)
    return new_list


x= replace_blank_strings_in_lists_of_lists(y)
print x

Jest to przydatne do wysyłania list list do bazy danych mysql, która nie przyjmuje pustych pól dla niektórych pól (pola oznaczone w schemacie jako NN. W moim przypadku było to spowodowane złożonym kluczem podstawowym).


-1

Przeprowadziłem pewne eksperymenty z ciągami takimi jak „”, „”, „\ n” itd. Chcę, aby właściwość NotNhitespace miała wartość True tylko wtedy, gdy zmienna foo jest łańcuchem z co najmniej jednym znakiem spacji. Używam Pythona 3.6. Oto, z czym skończyłem:

isWhitespace = str is type(foo) and not foo.strip()
isNotWhitespace = str is type(foo) and not not foo.strip()

W razie potrzeby zawiń to w definicji metody.


-3

Jak napisano powyżej, ale z pomyłką.

def isNoneOrEmptyOrBlankString (myString):
    if myString:
        if not myString.strip():
            return True
        else:
            return False
    return False

Tylko przetestowane: Jego powróci kod True ""i " "i fałsz dla "a"(tak jak oczekiwano). Twój kod zwraca to samo, z wyjątkiem pustego ciągu zwraca True, czego nie powinien.
AbcAeffchen

sry zbyt zmęczony: Twój kod zwraca False dla pustego ciągu.
AbcAeffchen

Ten kod jest nieprawidłowy. Zwracamy wartość False, jeśli ciąg znaków jest pusty lub żaden.
rubel
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.