Python: najbardziej idiomatyczny sposób konwersji None na pusty ciąg?


156

Jaki jest najbardziej idiomatyczny sposób na wykonanie następujących czynności?

def xstr(s):
    if s is None:
        return ''
    else:
        return s

s = xstr(a) + xstr(b)

aktualizacja: Włączam sugestię Trypticha, aby użyć str (s), co sprawia, że ​​ta rutynowa działa dla innych typów oprócz ciągów. Jestem pod ogromnym wrażeniem sugestii lambda Vinaya Sajipa, ale chcę, aby mój kod był stosunkowo prosty.

def xstr(s):
    if s is None:
        return ''
    else:
        return str(s)

7
Podoba mi się twoja oryginalna składnia. Myślę, że jest już dość jasny i łatwy do odczytania.
— GuiSim

1
@GuiSim: Mogę być stronniczy, ale moja odpowiedź brzmi prawie jak normalne angielskie zdanie ...
— SilentGhost

1
„Jeśli s ma wartość Brak, zwróć pusty ciąg; w przeciwnym razie zwróć [ciąg] s.” Kod z pytania również brzmi jak normalne angielskie zdanie.

a) Jeśli ciąg spochodzi z wyszukiwaniadict.get(key, '')
— dyktowania, w

b) Jeśli chcesz tę konwersję ciągów tylko do formatowania wyjściowego (np. do drukowania), możesz bezpośrednio wykonać '... {}'. format (dict.get (1)) `
— smci

Odpowiedzi:


94

Jeśli faktycznie chcesz, aby Twoja funkcja zachowywała się jak funkcja str()wbudowana, ale zwracała pusty ciąg, gdy argument ma wartość None, zrób to:

def xstr(s):
    if s is None:
        return ''
    return str(s)

Zatrzymuję inne, ale dzięki za wskazówkę str (s), więc można obsłużyć wiele typów. miły!
— Mark Harrison

11
Lub po prostuxstr = lambda s: '' if s is None else str(s)
— Michael Mior

2
Uwielbiam pisać if not s:zamiastif s is None
— guneysus

6
@guneysus Nie są takie same: not False == Trueale False is None == False.
— Lynn,

Dzięki @Lynn masz rację. Zrozumiałem swoją winę. Ale wiem (lub zakładam) szawsze typ in str / unicode lub None. Tak, Falseto wartość, ale wolę taki sposób, który oszczędza klawiaturę i oczy;)
— guneysus

143
def xstr(s):
    return '' if s is None else str(s)

3
Ta składnia została wprowadzona w 2.5; we wcześniejszych wersjach Pythona można użyć return s is not None and s or ''.
— Ben Blank,

8
Odwróciłbym to, aby podkreślić bardziej powszechny przypadek: zwraca s, jeśli s jest inny niż Nikt inny ""
— Ber,

5
@Ber: Zachowałbym to tak, jak jest, aby uniknąć podwójnego negatywu.
— Nikhil Chelliah

8
To jest dobry przykład tego, jak .. and .. or ..zawodzi i dlaczego preferowana jest opcja if-else. Istnieją dwa subtelne błędy s is not None and s or ''.

1
return '' if not s else str(s)
— Iqbal

110

Prawdopodobnie najkrótszy str(s or '')

Ponieważ None jest fałszem, a „x lub y” zwraca y, jeśli x jest fałszywe. Aby uzyskać szczegółowe wyjaśnienie, zobacz Operatory boolowskie . Jest krótki, ale niezbyt wyraźny.


1
to wspaniale, dziękuję! Nigdy nie myślałem o używaniu w orten sposób
— user25064

15
To nie działa, jeśli swynosi 0, False lub jakakolwiek fałszywa wartość
— wisbucky

4
Cóż, nie ma o tym wzmianki w wymaganiach operatora, więc nie widzę tutaj twojego punktu widzenia.
— dorvak

2
@dorvak W OP dość jasno sprecyzowano, że dane wyjściowe powinny mieć wartość ''iff s is None. Wszystkie inne dane wejściowe powinny zostać zwrócone s(lub str(s)w poprawionym żądaniu).
— StvnW

2
@fortea: to nie zadziała. Jeśli stak None, wynikiem xstr()powinien być pusty ciąg, ale str(None)daje ciąg "None", który jest zwracany (ponieważ ciąg "None"nie jest fałszywą wartością.
— dreamlax

97

Jeśli wiesz, że wartość zawsze będzie ciągiem lub None:

xstr = lambda s: s or ""

print xstr("a") + xstr("b") # -> 'ab'
print xstr("a") + xstr(None) # -> 'a'
print xstr(None) + xstr("b") # -> 'b'
print xstr(None) + xstr(None) # -> ''

1
zdecydowanie najbardziej pytoniczny. Używa faktu, że Python traktuje None, pustą listę, pusty łańcuch, 0 itd. Jako fałsz. Wykorzystuje również fakt, że instrukcja lub zwraca pierwszy element, który jest prawdziwy, lub ostatni element podany elementowi lub (lub grupom ors). Również to wykorzystuje funkcje lambda. Dałbym ci +10, ale oczywiście mi nie pozwoli.
— Matt

11
Spowoduje to przekonwertowanie wartości 0 i False (i wszystkiego innego, co po przekazaniu do bool ())
— daje

9
Nie sądzę, że jest to „zdecydowanie najbardziej pytoniczne”. Jest to powszechny idiom w innych językach i nie sądzę, aby używanie go w Pythonie było niewłaściwe, ale wyrażenia warunkowe zostały wprowadzone właśnie w celu uniknięcia takich sztuczek.
— Roberto Bonvallet

2
To sprawia [], że {}itp. Dają taki sam wynik jak None, co nie jest pożądane. xstr(False)w szczególności powinno być "False"zamiast "". Nadużywanie lambd to kiepski przykład, użyj def xstr(s): return s or ""ir, jeśli chcesz, aby wszystko było w jednej linii.

5
Zwróć uwagę, że na początku określiłem moją odpowiedź słowami „Jeśli wiesz, że wartością zawsze będzie ciąg znaków lub Brak”.
— Vinay Sajip

59

return s or '' będzie działać dobrze dla podanego problemu!


4
Warto zauważyć, że da to inny wynik, gdy s jest fałszywe lub 0 (co nie jest oryginalnym pytaniem typu string, ale zaktualizowanym).
— Oddthinking

@Oddthinking s = Falselub s = 0najprawdopodobniej byłby skrajnym przypadkiem w jego użyciu i można go łatwo złagodzić, pisząc to jakoreturn str(s or '')
— Willem van Ketwich

@WillemvanKetwich: To ma dokładnie ten sam problem: s (False) powinno zwracać „False”, a nie „”. s (0) powinno zwracać „0”, a nie „”. Podobnie jest w przypadku obiektu, który definiuje __bool__ lub __nonzero__.
— Dziwne myślenie

@Oddthinking Rozumiem twój punkt widzenia. W każdym razie, jeśli jest używany wyłącznie do obiektów łańcuchowych, takich jak w pytaniu PO, nie powinno to stanowić problemu.
— Willem van Ketwich

@WillemvanKetwich: Spójrz na zaktualizowane pytanie i zastrzeżenie w moim komentarzu - zostało to omówione,
— Oddthinking

14
def xstr(s):
   return s or ""

4
Spowoduje to powrót ''do 0, [], {}, Falsei fałszywie jak wartości, która nie ma co prosić o plakat.
— StvnW

1
po prostu umieść str ([...]) wokół s: def xstr(s): return str(s) or ""
— Federico Simonetta

8

Funkcjonalny sposób (jedna linijka)

xstr = lambda s: '' if s is None else s

1
"def xstr (s): return '' if s is None else s" też jest on-linerem, Python nie jest jednak tak rygorystyczny z białymi
— znakami

2
To nie jest prawdziwa jedna linijka, jest po prostu napisana w jednej linii g
— Dario

1
w jakim sensie to nie jest prawdziwy onliner? sprawdź swój interpreter - to nie jest błąd składni. pod każdym względem jest bardziej realne niż lambda ^ _ ^
— SilentGhost

2
PEP 8, których powinieneś używać def zamiast przypisywać lambdę do zmiennej. Jedyną prawdziwą zaletą lambdy jest to, że możesz pisać jako część wyrażenia (na przykład przekazując do innej funkcji) i ta zaleta jest tracona w kodzie takim jak ten. Ja też to robiłem, dopóki nie zauważyłem, że def można zapisać w jednej linii, a wtedy PEP 8 wskazał mi drogę. ZAWSZE podążaj za bogami pytonów.
— Guy,

8

Zgrabna jedna linijka do zrobienia tego budynku na niektórych innych odpowiedziach:

s = (lambda v: v or '')(a) + (lambda v: v or '')(b)

lub po prostu:

s = (a or '') + (b or '')

Po co w ogóle wspominać (lambda v: v or '')?
— Tvde1

Dlaczego nie? 2 napiwki w cenie 1! 😀
— Willem van Ketwich

1
Należy pamiętać, że Falsepusta lista również zostanie zmieniona na „”.
— Nik O'Lai

to samo dla 0itd.
— Walter Tross

6
def xstr(s):
    return {None:''}.get(s, s)

Myślę, że jest raczej pythonowy - a co powiesz na ten: "xstr = lambda s: {None: ''}. Get (s, s)" - redukuje całość do jednej linijki.
— Juergen

14
Niepotrzebnie wolne (dodatkowe tworzenie i wyszukiwanie dyktowania) i trudniejsze do odczytania. Całkiem nieszablonowy.
— Tryptyk

Masz rację. Jest raczej zgubny, ale unika warunkowego skoku w kodzie bajtowym Pythona.
— tobidope

4
Wywołanie funkcji get () implikuje co najmniej jeden dodatkowy skok warunkowy.
— Tryptyk

1
Nie byłbym w stanie powiedzieć, co to powinno zrobić, nie znając pytania lub nie patrząc w górę get.
— Dario

5

Używam funkcji max:

max(None, '')  #Returns blank
max("Hello",'') #Returns Hello

Działa jak urok;) Po prostu umieść swój napis w pierwszym parametrze funkcji.


5
To działa, ponieważ „str”> „NoneType” i jest specyficzne dla CPythona. Z instrukcji : „Obiekty różnych typów z wyjątkiem numerów są uporządkowane według nazw typów”. Również to nie zadziała w Pythonie 3000, ponieważ porównanie między typami nie jest już dozwolone (TypeError: unorderable types: str ()> NoneType ()). Zobacz, jak Python porównuje ciąg i int?
— plok

Dobrze wiedzieć, dziękuję, więc nie jest to dobry pomysł, aby przejść dalej z kodem zgodnym z Python 3.x.
— radtek

4

Odmiana powyższego, jeśli chcesz być kompatybilny z Pythonem 2.4

xstr = lambda s: s is not None and s or ''

2

Jeśli chodzi o formatowanie ciągów, możesz wykonać następujące czynności:

from string import Formatter

class NoneAsEmptyFormatter(Formatter):
    def get_value(self, key, args, kwargs):
        v = super().get_value(key, args, kwargs)
        return '' if v is None else v

fmt = NoneAsEmptyFormatter()
s = fmt.format('{}{}', a, b)

1
def xstr(s):
    return s if s else ''

s = "%s%s" % (xstr(a), xstr(b))

5
To zwróci pusty ciąg dla wszystkich wartości podobnych do fałszu, o co nie prosił plakat.
— Tryptyk

1

Zawsze możemy uniknąć rzutowania typów w scenariuszach opisanych poniżej.

customer = "John"
name = str(customer)
if name is None
   print "Name is blank"
else: 
   print "Customer name : " + name

W powyższym przykładzie, jeśli wartością zmiennej customer jest None, zostanie ona dalej rzutowana, gdy zostanie przypisana do 'name'. Porównanie w klauzuli „if” zawsze kończy się niepowodzeniem.

customer = "John" # even though its None still it will work properly.
name = customer
if name is None
   print "Name is blank"
else: 
   print "Customer name : " + str(name)

Powyższy przykład zadziała poprawnie. Takie scenariusze są bardzo powszechne, gdy wartości są pobierane z adresu URL, JSON lub XML, a nawet wartości wymagają dalszego rzutowania typów w celu dowolnej manipulacji.


0

Użyj oceny zwarcia:

s = a or '' + b or ''

Ponieważ + nie jest zbyt dobrą operacją na łańcuchach, lepiej użyj ciągów formatu:

s = "%s%s" % (a or '', b or '')

2
Spowoduje to również przekonwertowanie „a” na puste łańcuchy dla wszystkich wartości typu false, a nie tylko None. Na przykład puste krotki, listy i dykty zostaną przekonwertowane na puste łańcuchy, co nie jest tym, co określono w OP.
— Tryptyk

+to doskonały operator na dwa struny. Kiedy próbujesz użyć go do połączenia dziesiątek, masz kłopoty. Dla dwojga prawdopodobnie będzie to szybsze niż inne opcje; tak czy inaczej, jest w hałasie.
— kquinn

+1 dla mnie, bo to jest dokładnie to, czego potrzebuję w moim przypadku: lambda lub funkcja zastępująca pojedynczy operator ( or) wydaje mi się trochę przesadą ... Nie mam przypadków innych fałszywych wartości - ani str, ani None. Poza komentarzem na temat +operatora, który może zależeć od konkretnego scenariusza i może wymagać analizy porównawczej, ta odpowiedź nie zasługuje na -1
— miejski

-3

Użyj ciągu F, jeśli używasz języka Python w wersji 3.7

xstr = F"{s}"

1
To jest błędne i zwraca ciąg, 'None'jeśli sjest None.
— Lawrence,
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.