Python: die idiomatischste Art, None in eine leere Zeichenfolge umzuwandeln?

156

Was ist der idiomatischste Weg, um Folgendes zu tun?

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

s = xstr(a) + xstr(b)

Update: Ich nehme Tryptichs Vorschlag auf, str (s) zu verwenden, wodurch diese Routine für andere Typen als Strings funktioniert. Ich bin schrecklich beeindruckt von Vinay Sajips Lambda-Vorschlag, aber ich möchte meinen Code relativ einfach halten.

def xstr(s):
    if s is None:
        return ''
    else:
        return str(s)
Mark Harrison
quelle
7
Ich mag deine ursprüngliche Syntax. Ich denke, es ist schon ziemlich klar und leicht zu lesen.
GuiSim
1
@GuiSim: Ich könnte voreingenommen sein, aber meine Antwort liest sich fast wie ein normaler englischer Satz ...
SilentGhost
1
"Wenn s None ist, geben Sie eine leere Zeichenfolge zurück. Andernfalls geben Sie [Zeichenfolge von] s zurück." Der Code aus der Frage liest sich auch wie ein normaler englischer Satz.
a) Wenn die Zeichenfolge saus einer Diktatsuche stammt, bei der der Schlüssel nicht gefunden wurde, verwenden Siedict.get(key, '')
smci
b) Wenn Sie diese Zeichenfolgenkonvertierung nur für die Ausgabeformatierung (z. B. für den Druck) möchten, können Sie direkt das Format '... {}' (dict.get (1)) `
smci

Antworten:

94

Wenn Sie möchten, dass sich Ihre Funktion wie die str()integrierte Funktion verhält , aber eine leere Zeichenfolge zurückgibt, wenn das Argument Keine lautet, gehen Sie folgendermaßen vor:

def xstr(s):
    if s is None:
        return ''
    return str(s)
Triptychon
quelle
Ich behalte das andere, aber danke für den Str (s) -Tipp, damit mehrere Typen verarbeitet werden können. nett!
Mark Harrison
11
Oder einfachxstr = lambda s: '' if s is None else str(s)
Michael Mior
2
Ich liebe es zu if not s:if s is None
tippen
6
@guneysus Sie sind nicht gleich: not False == Trueaber False is None == False.
Lynn
Danke @Lynn du hast recht. Ich erkannte meine Schuld. Aber ich kenne (oder nehme an) simmer einen in str / unicode Typ oder None. Ja, Falseist ein Wert, aber ich bevorzuge diesen Weg, der meine Tastatur und Augen rettet;)
Guneysus
143
def xstr(s):
    return '' if s is None else str(s)
SilentGhost
quelle
3
Diese Syntax wurde in 2.5 eingeführt; Für frühere Versionen von Python können Sie verwenden return s is not None and s or ''.
Ben Blank
8
Ich würde es umdrehen, um den eher beginnenden Fall hervorzuheben: s zurückgeben, wenn s nicht Sonst ist ""
Ber
5
@Ber: Ich würde es so lassen wie es ist, um ein doppeltes Negativ zu vermeiden.
Nikhil Chelliah
8
Dies ist ein gutes Beispiel dafür, wie .. and .. or ..fehlschlägt und warum if-else bevorzugt wird. Es gibt zwei subtile Fehler s is not None and s or ''.
1
return '' if not s else str(s)
Iqbal
106

Wahrscheinlich wäre das kürzeste str(s or '')

Weil Keine falsch ist und "x oder y" y zurückgibt, wenn x falsch ist. Eine ausführliche Erläuterung finden Sie unter Boolesche Operatoren . Es ist kurz, aber nicht sehr explizit.

dorvak
quelle
1
das ist so toll, danke! Ich habe nie daran gedacht, ordiesen Weg zu
benutzen
15
Dies funktioniert nicht, wenn s0, Falsch oder ein falscher Wert ist
wisbucky
4
Nun, das wird in der Anforderung der Operation nicht erwähnt, daher verstehe ich Ihren Standpunkt hier nicht.
Dorvak
2
@dorvak Das OP ist ziemlich explizit in Bezug auf die Anforderung, dass die Ausgabe ''iff sein soll s is None. Alle anderen Eingaben sollten zurückgegeben werden s(oder str(s)in der überarbeiteten Anfrage).
StvnW
2
@fortea: das wird nicht funktionieren. Wenn sist None, das Ergebnis xstr()sollte ein leerer String sein, aber str(None)gibt die Zeichenfolge "None", die ist , was zurückgegeben wird (da die Zeichenfolge "None"kein falsy Wert.
dreamlax
97

Wenn Sie wissen, dass der Wert immer entweder eine Zeichenfolge oder Keine ist:

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) # -> ''
Vinay Sajip
quelle
1
bei weitem das pythonischste. Verwendet die Tatsache, dass Python None, eine leere Liste, eine leere Zeichenfolge, 0 usw. als falsch behandelt. Verwendet auch die Tatsache, dass die Anweisung oder das erste Element zurückgibt, das wahr ist, oder das letzte Element, das dem oder (oder Gruppen von ors) gegeben wurde. Auch dies verwendet Lambda-Funktionen. Ich würde dir +10 geben, aber offensichtlich lässt es mich nicht.
Matt
11
Dies wird 0 und False konvertieren (und alles andere, was als False ausgewertet wird, wenn es an bool () übergeben wird)
Arkady
9
Ich denke nicht, dass es "bei weitem das pythonischste" ist. Es ist eine gängige Redewendung in anderen Sprachen, und ich denke nicht, dass es falsch ist, es in Python zu verwenden, aber bedingte Ausdrücke wurden genau eingeführt, um solche Tricks zu vermeiden.
Roberto Bonvallet
2
Dies macht [], {}usw. gibt das gleiche Ergebnis wie None, was nicht erwünscht ist. xstr(False)insbesondere sollte "False"statt sein "". Der Missbrauch von Lambdas ist ein schlechtes Beispiel. Verwenden def xstr(s): return s or ""Sie ir, um alles in einer Zeile zu halten.
5
Beachten Sie, dass ich meine Antwort zu Beginn mit "Wenn Sie wissen, dass der Wert immer entweder eine Zeichenfolge oder keine ist" qualifiziert habe.
Vinay Sajip
59

return s or '' funktioniert gut für Ihr angegebenes Problem!

Alex Martelli
quelle
4
Es ist erwähnenswert, dass dies zu einem anderen Ergebnis führt, wenn s False oder 0 ist (was nicht die ursprüngliche, sondern die aktualisierte String-Frage ist).
Oddthinking
@Oddthinking s = Falseoder s = 0wäre höchstwahrscheinlich ein Randfall in seiner Verwendung und könnte leicht gemildert werden, indem man es alsreturn str(s or '')
Willem van Ketwich
@ WillemvanKetwich: Das hat genau das gleiche Problem: s (False) sollte 'False' zurückgeben, nicht ''. s (0) sollte '0' zurückgeben, nicht ''. Ebenso für ein Objekt, das __bool__ oder __nonzero__ definiert.
Oddthinking
@Oddthinking Ich verstehe deinen Standpunkt. In jedem Fall sollte es kein Problem sein, wenn es ausschließlich für Zeichenfolgenobjekte verwendet wird, wie in der Frage des OP.
Willem van Ketwich
@ WillemvanKetwich: Werfen Sie einen Blick auf die aktualisierte Frage und die Einschränkung in meinem Kommentar - dies wurde behandelt,
Oddthinking
14
def xstr(s):
   return s or ""
Krystian Cybulski
quelle
4
Dies gibt ''für 0, [], {}, Falseund falsch wie Werte, das ist nicht das, was das Plakat gefragt.
StvnW
1
Setzen Sie einfach str ([...]) um s: def xstr(s): return str(s) or ""
Federico Simonetta
8

Funktionsweise (Einzeiler)

xstr = lambda s: '' if s is None else s
Dario
quelle
1
"def xstr (s): return '' if s is None else s" ist auch ein
Onliner
2
Es ist kein richtiger Einzeiler, es ist nur in einer Zeile geschrieben g
Dario
1
Inwiefern ist es kein echter Onliner? Checken Sie Ihren Interpreter ein - es ist kein Syntaxfehler. In jeder Hinsicht ist es viel realer als Lambda ^ _ ^
SilentGhost
2
PEP 8-Arten, die Sie def verwenden sollten, anstatt einer Variablen Lambda zuzuweisen. Der einzige wirkliche Vorteil von Lambda besteht darin, dass Sie als Teil des Ausdrucks schreiben können (z. B. an eine andere Funktion übergeben) und dieser Vorteil in Code wie diesem verloren geht. Ich habe das auch gemacht, bis ich bemerkte, dass def in einer Zeile geschrieben werden kann, und dann zeigte mir PEP 8 den Weg. Folgen Sie IMMER den Python-Göttern.
Guy
8

Ein ordentlicher Einzeiler, um dieses Gebäude auf einigen der anderen Antworten aufzubauen:

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

oder auch nur:

s = (a or '') + (b or '')
Willem van Ketwich
quelle
Warum überhaupt erwähnen (lambda v: v or '')?
Tvde1
Warum nicht? 2 Tipps zum Preis von 1! 😀
Willem van Ketwich
1
Bitte beachten Sie, dass eine Falseleere Liste ebenfalls auf '' gesetzt wird.
Nik O'Lai
Gleiches gilt für 0usw.
Walter Tross
6
def xstr(s):
    return {None:''}.get(s, s)
tobidope
quelle
Ich denke, es ist ziemlich pythonisch - wie wäre es mit diesem: "xstr = lambda s: {None: ''}. Get (s, s)" - reduziert das Ganze auf einen Einzeiler.
Jürgen
14
Unnötig langsam (zusätzliche Diktatkonstruktion und Suche) und schwerer zu lesen. Ziemlich unpythonisch.
Triptychon
Du hast recht. Es ist ziemlich perlish, aber es vermeidet einen bedingten Sprung im Python-Bytecode.
tobidope
4
Der Funktionsaufruf get () impliziert mindestens einen zusätzlichen bedingten Sprung.
Triptychon
1
Ich würde nicht sagen können, was dies tun soll, ohne die Frage zu kennen oder nachzuschauen get.
Dario
5

Ich benutze die Max-Funktion:

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

Funktioniert wie ein Zauber;) Setzen Sie einfach Ihren String in den ersten Parameter der Funktion.

radtek
quelle
5
Dies funktioniert, weil 'str'> 'NoneType' und CPython-spezifisch ist. Aus dem Handbuch : "Objekte unterschiedlicher Typen mit Ausnahme von Nummern werden nach Typnamen sortiert". Dies funktioniert auch in Python 3000 nicht, da ein Vergleich zwischen Typen nicht mehr zulässig ist (TypeError: unordable types: str ()> NoneType ()). Siehe Wie vergleicht Python String und Int?
Plok
Gut zu wissen, danke, also keine gute Idee, mit Python 3.x-kompatiblem Code voranzukommen.
Radtek
4

Variation oben, wenn Sie mit Python 2.4 kompatibel sein müssen

xstr = lambda s: s is not None and s or ''
Peter Ericson
quelle
2

Wenn es darum geht, Zeichenfolgen zu formatieren, können Sie Folgendes tun:

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)
Maciek
quelle
1
def xstr(s):
    return s if s else ''

s = "%s%s" % (xstr(a), xstr(b))
phillc
quelle
5
Dies gibt eine leere Zeichenfolge für alle falsch ähnlichen Werte zurück, was im Poster nicht gefordert wurde.
Triptychon
1

In den unten erläuterten Szenarien können wir Typumwandlungen immer vermeiden.

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

Im obigen Beispiel wird für den Fall, dass der Wert des variablen Kunden None ist, das Casting weiter ausgeführt, während er dem Namen zugewiesen wird. Der Vergleich in der 'if'-Klausel schlägt immer fehl.

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)

Das obige Beispiel funktioniert ordnungsgemäß. Solche Szenarien sind sehr häufig, wenn Werte von URL, JSON oder XML abgerufen werden oder sogar Werte für jede Manipulation eine weitere Typumwandlung benötigen.

Pralhad Narsinh Sonar
quelle
0

Kurzschlussauswertung verwenden:

s = a or '' + b or ''

Da + keine sehr gute Operation für Zeichenfolgen ist, sollten Sie Formatzeichenfolgen besser verwenden:

s = "%s%s" % (a or '', b or '')
Sharjeel
quelle
2
Dadurch wird auch 'a' für alle falsch ähnlichen Werte in leere Zeichenfolgen konvertiert, nicht nur für Keine. Beispielsweise werden leere Tupel, Listen und Diktate in leere Zeichenfolgen konvertiert, was im OP nicht angegeben ist.
Triptychon
+ist ein perfekter Operator für zwei Saiten. Wenn Sie versuchen, damit Dutzenden beizutreten, haben Sie Probleme. Für zwei wird es wahrscheinlich schneller sein als andere Optionen; In jedem Fall liegt es im Lärm.
Kquinn
+1 für mich, weil dies genau das ist, was ich in meinem Fall brauche: Lambda oder eine Funktion zum Ersetzen eines einzelnen Operators ( or) scheint mir ein bisschen übertrieben zu sein ... Ich habe keine Fälle von anderen falschen Werten - entweder str oder None. Abgesehen von dem Kommentar zum +Betreiber, der möglicherweise von einem bestimmten Szenario abhängt und ein Benchmarking erfordert , verdient diese Antwort keinen -1
urban
-3

Verwenden Sie die F-Zeichenfolge, wenn Sie Python v3.7 verwenden

xstr = F"{s}"
user781486
quelle
1
Dies ist falsch und gibt die Zeichenfolge zurück, 'None'wenn dies der Fall sist None.
Lawrence