Python: il modo più idiomatico per convertire None in stringa vuota?


156

Qual è il modo più idiomatico per fare quanto segue?

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

s = xstr(a) + xstr(b)

aggiornamento: sto incorporando il suggerimento di Tryptich di usare str (s), che fa funzionare questa routine per altri tipi oltre alle stringhe. Sono terribilmente colpito dal suggerimento lambda di Vinay Sajip, ma voglio mantenere il mio codice relativamente semplice.

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

7
Mi piace la tua sintassi originale. Penso che sia già abbastanza chiaro e facile da leggere.
GuiSim,

1
@GuiSim: potrei essere di parte, ma la mia risposta sembra quasi una normale frase inglese ...
SilentGhost,

1
"Se s è Nessuno, restituisce una stringa vuota; in caso contrario, restituisce [stringa di] s." Il codice della domanda si legge anche come una normale frase inglese.

a) Se la stringa sproviene da una ricerca di dict in cui non è stata trovata la chiave, utilizzaredict.get(key, '')
smci

b) Se vuoi solo questa conversione di stringhe per la formattazione dell'output (ad es. per la stampa), puoi fare direttamente '... {}'. format (dict.get (1)) `
smci

Risposte:


94

Se vuoi che la tua funzione si comporti come quella str()incorporata, ma restituisca una stringa vuota quando l'argomento è Nessuno, procedi come segue:

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

Sto mantenendo il resto, ma grazie per il suggerimento str (s) in modo da poter gestire più tipi. simpatico!
Mark Harrison,

11
O semplicementexstr = lambda s: '' if s is None else str(s)
Michael Mior,

2
Adoro scrivere if not s:invece diif s is None
guneysus il

6
@guneysus Non sono gli stessi: not False == Truema False is None == False.
Lynn,

Grazie @Lynn hai ragione. Ho realizzato la mia colpa. Ma so (o presumo) ssempre un tipo in str / unicode o None. Sì, Falseè un valore, ma preferisco questo modo che mi salva la tastiera e gli occhi;)
guneysus

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

3
Questa sintassi è stata introdotta in 2.5; per le versioni precedenti di Python, è possibile utilizzare return s is not None and s or ''.
Ben Blank,

8
Lo ribalterei per enfatizzare il caso più comune: restituire s se s non è nessun altro ""
Ber

5
@Ber: lo terrei così com'è, per evitare un doppio negativo.
Nikhil Chelliah,

8
Questo è un buon esempio di come .. and .. or ..fallisce e perché è preferito if-else. Ci sono due bug sottili dentro s is not None and s or ''.

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

108

Probabilmente il più breve sarebbe str(s or '')

Perché None è False e "x o y" restituisce y se x è falso. Vedere Operatori booleani per una spiegazione dettagliata. È breve, ma non molto esplicito.


1
è fantastico, grazie! Non or
avrei

15
Questo non funziona se sè 0, False o qualsiasi valore
errato

4
Bene, questo non è menzionato nei requisiti dell'operazione, quindi non vedo il tuo punto qui.
Dorvak,

2
@dorvak L'OP è abbastanza esplicito sul requisito che l'output dovrebbe essere ''iff s is None. Tutti gli altri input devono essere restituiti s(o str(s)nella richiesta rivista).
StvnW,

2
@fortea: che non funzionerà. Se sè None, il risultato di xstr()dovrebbe essere una stringa vuota, ma str(None)dà la corda "None", che è ciò che viene restituito (dal momento che la stringa "None"non è un valore falsy.
dreamlax

97

Se sai che il valore sarà sempre una stringa o Nessuno:

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
di gran lunga il più pitonico. Utilizza il fatto che Python considera None, un elenco vuoto, una stringa vuota, 0, ecc. Come falso. Utilizza anche il fatto che l'istruzione o restituisce il primo elemento che è vero o l'ultimo elemento dato al o (o ai gruppi di o). Anche questo utilizza le funzioni lambda. Ti darei +10 ma ovviamente non me lo permette.
Matt,

11
Questo convertirà 0 e False (e qualsiasi altra cosa che valuti in False una volta passato a bool ())
Arkady,

9
Non credo sia "di gran lunga il più pitonico". È un linguaggio comune in altre lingue e non credo sia sbagliato usarlo in Python, ma le espressioni condizionali sono state introdotte proprio per evitare trucchi come questo.
Roberto Bonvallet,

2
Questo rende [], {}ecc. Fornisce lo stesso risultato di None, che non è desiderato. xstr(False), in particolare, dovrebbe essere "False"invece di "". Abusare di lambda è un cattivo esempio, usa def xstr(s): return s or ""ir per mantenere tutto su una riga.

5
Nota che all'inizio ho qualificato la mia risposta con "Se sai che il valore sarà sempre una stringa o Nessuno".
Vinay Sajip,

59

return s or '' funzionerà perfettamente per il problema dichiarato!


4
Vale la pena notare che questo darà un risultato diverso per quando s è False o 0 (che non è la domanda di stringa originale, ma quella aggiornata.)
Pensiero strano

@Oddthinking s = Falseo s = 0molto probabilmente sarebbe un caso limite nel suo uso e potrebbe essere facilmente mitigato scrivendolo comereturn str(s or '')
Willem van Ketwich,

@WillemvanKetwich: ha esattamente lo stesso problema: s (False) dovrebbe restituire 'False', non ''. s (0) dovrebbe restituire '0', non ''. Allo stesso modo per un oggetto che definisce __bool__ o __nonzero__.
Pensando in modo strano

@Spensandoci, vedo il tuo punto. In ogni caso, se utilizzato esclusivamente per oggetti stringa come nella domanda dell'OP, non dovrebbe costituire un problema.
Willem van Ketwich,

@WillemvanKetwich: dai un'occhiata alla domanda aggiornata e alle avvertenze nel mio commento - questo è stato coperto,
Stranamente,


8

Modo funzionale (one-liner)

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

1
"def xstr (s): return '' if s is None else s" è anch'esso in linea,
dopotutto

2
Non è un vero one-liner, è solo scritto in una riga g
Dario,

1
in che senso non è un vero onliner? controlla nel tuo interprete - non è un errore di sintassi. a tutti gli effetti è molto più reale di lambda ^ _ ^
SilentGhost,

2
Specie PEP 8 che dovresti usare def invece di assegnare lambda a una variabile. L'unico vero vantaggio di lambda è che puoi scrivere come parte dell'espressione (passando ad un'altra funzione per esempio) e quel vantaggio si perde in codice come questo. Lo facevo anche io, fino a quando ho notato che def può essere scritto in una riga, e poi PEP 8 mi ha mostrato la strada da percorrere. Segui SEMPRE gli dei del pitone.
Guy,

8

Un one-liner pulito per fare questo edificio su alcune delle altre risposte:

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

o anche solo:

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

Perché anche menzionarlo (lambda v: v or '')?
Tvde1

Perchè no? 2 consigli al prezzo di 1! 😀
Willem van Ketwich,

1
Tieni presente che Falseanche l'elenco vuoto verrà trasformato in "".
Nik O'Lai,

lo stesso per 0, ecc.
Walter Tross,

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

Penso che sia piuttosto pitonico - che ne dici di questo: "xstr = lambda s: {None: ''}. Get (s, s)" - riduce il tutto a una riga.
Juergen,

14
Inutilmente lento (costruzione e ricerca extra dict) e più difficile da leggere. Abbastanza poco sincero.
Trittico,

Hai ragione. È piuttosto perlish ma evita un salto condizionale nel bytecode python.
tobidope,

4
La chiamata della funzione get () implica almeno un salto condizionale aggiuntivo.
Trittico,

1
Non sarei in grado di dire cosa dovrebbe fare senza conoscere la domanda o guardare in alto get.
Dario,

5

Uso la funzione max:

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

Funziona come un incantesimo;) Basta inserire la stringa nel primo parametro della funzione.


5
Questo funziona perché 'str'> 'NoneType', ed è specifico per CPython. Dal manuale : "Gli oggetti di tipi diversi, tranne i numeri, sono ordinati in base al nome del tipo". Inoltre, questo non funzionerà in Python 3000, poiché il confronto tra tipi non è più consentito (TypeError: tipi non ordinabili: str ()> NoneType ()). Vedi In che modo Python confronta string e int?
visita il

Buono a sapersi grazie, quindi non è una buona idea andare avanti con il codice compatibile con Python 3.x.
Radtek,

4

Variazione di quanto sopra se è necessario essere compatibili con Python 2.4

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

2

Se si tratta di formattare le stringhe, è possibile effettuare le seguenti operazioni:

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
Ciò restituirà una stringa vuota per tutti i valori falsi, che non è quello richiesto dal poster.
Trittico,

1

Possiamo sempre evitare il cast di tipi negli scenari spiegati di seguito.

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

Nell'esempio sopra, nel caso in cui il valore del cliente variabile sia Nessuno, viene ulteriormente trasmesso mentre viene assegnato a "nome". Il confronto nella clausola 'if' fallirà sempre.

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)

L'esempio sopra funzionerà correttamente. Tali scenari sono molto comuni quando i valori vengono recuperati da URL, JSON o XML o anche i valori richiedono ulteriore cast di tipi per qualsiasi manipolazione.


0

Usa la valutazione del corto circuito:

s = a or '' + b or ''

Poiché + non è un'ottima operazione sulle stringhe, utilizzare meglio le stringhe di formato:

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

2
Questo inoltre convertirà 'a' in stringhe vuote per tutti i valori falsi, non solo Nessuno. Ad esempio, le tuple, gli elenchi e i dicts vuoti verranno convertiti in stringhe vuote, che non è quello specificato dall'OP.
Trittico,

+è un ottimo operatore per due corde. È quando provi ad usarlo per unirti a dozzine che hai problemi. Per due, probabilmente sarà più veloce di altre opzioni; in entrambi i casi, è nel rumore.
kquinn,

+1 per me perché questo è esattamente ciò di cui ho bisogno nel mio caso: lambda o la funzione per sostituire un singolo operatore ( or) sembra un po 'eccessiva per me ... Non ho casi di altri valori falsamente - né str né nessuno. A parte il commento sull'operatore +, che potrebbe dipendere da uno scenario specifico e potrebbe essere necessario un benchmarking, questa risposta non merita un -1
urbano

-3

Usa la stringa F se stai usando python v3.7

xstr = F"{s}"

1
Questo è sbagliato e restituisce la stringa 'None'se lo sè None.
Lawrence
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.