Python: ¿la forma más idiomática de convertir None en una cadena vacía?


156

¿Cuál es la forma más idiomática de hacer lo siguiente?

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

s = xstr(a) + xstr(b)

actualización: estoy incorporando la sugerencia de Tryptich de usar str (s), lo que hace que esta rutina funcione para otros tipos además de las cadenas. Estoy terriblemente impresionado por la sugerencia lambda de Vinay Sajip, pero quiero mantener mi código relativamente simple.

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

77
Me gusta tu sintaxis original. Creo que ya es bastante claro y fácil de leer.
GuiSim

1
@GuiSim: Yo podría estar sesgada, pero mi respuesta se lee casi como una frase normal de Inglés ...
SilentGhost

1
"Si s es Ninguno, entonces devuelve una cadena vacía; de lo contrario, devuelve [cadena de] s". El código de la pregunta también se lee como una oración normal en inglés.

a) Si la cadena sprovino de una búsqueda de dict donde no se encontró la clave, usedict.get(key, '')
smci

b) Si solo desea esta conversión de cadena para el formato de salida (por ejemplo, para imprimir), puede hacer directamente '... {}'. format (dict.get (1)) `
smci

Respuestas:


94

Si realmente desea que su función se comporte como la str()integrada, pero devuelva una cadena vacía cuando el argumento es Ninguno, haga esto:

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

Me quedo con el resto, pero gracias por la sugerencia str (s) para que se puedan manejar varios tipos. ¡bonito!
Mark Harrison el

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

2
Me encanta escribir en if not s:lugar deif s is None
guneysus

66
@guneysus No son lo mismo: not False == Truepero False is None == False.
Lynn

Gracias @ Lynn tienes razón. Me di cuenta de mi culpa. Pero sé (o asumo) ssiempre un tipo in / unicode o str None. Sí, Falsees un valor, pero prefiero esta forma que salva mi teclado y mis ojos;)
guneysus

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

3
Esta sintaxis se introdujo en 2.5; para versiones anteriores de Python, puede usar return s is not None and s or ''.
Ben Blank

8
Lo cambiaría para enfatizar el caso más común: devolver s si s no es Ninguno más ""
Ber

55
@Ber: Lo mantendría como está, para evitar una doble negativa.
Nikhil Chelliah

8
Este es un buen ejemplo de cómo .. and .. or ..falla y por qué se prefiere if-else. Hay dos errores sutiles en s is not None and s or ''.

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

108

Probablemente lo más corto sería str(s or '')

Porque Ninguno es falso, y "x o y" devuelve y si x es falso. Ver operadores booleanos para una explicación detallada. Es breve, pero no muy explícito.


1
esto es genial, gracias! Nunca pensé en usarlo de oresta manera
user25064

15
Esto no funciona si ses 0, Falso o cualquier valor
falso

44
Bueno, eso no se menciona en el requisito del operador, por lo que no veo su punto aquí.
dorvak

2
@dorvak El OP es bastante explícito sobre el requisito de que el resultado sea ''iff s is None. Todas las demás entradas deben regresar s(o str(s)en la solicitud revisada).
StvnW

2
@fortea: eso no funcionará. Si ses así None, el resultado xstr()debería ser una cadena vacía, pero str(None)da la cadena "None", que es lo que se devuelve (ya que la cadena "None"no es un valor falso.
dreamlax

97

Si sabe que el valor siempre será una cadena o Ninguno:

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
con mucho, el más pitónico. Utiliza el hecho de que python trata None, una lista vacía, una cadena vacía, 0, etc. como falsa. También utiliza el hecho de que la instrucción o devuelve el primer elemento que es verdadero o el último elemento dado a o (o grupos de ors). También esto usa funciones lambda. Te daría +10 pero obviamente no me deja.
Matt

11
Esto convertirá 0 y False (y cualquier otra cosa que se evalúe como False cuando se pase a bool ())
Arkady

9
No creo que sea "de lejos el más pitónico". Es un idioma común en otros idiomas, y no creo que esté mal usarlo en Python, pero las expresiones condicionales se introdujeron precisamente para evitar trucos como este.
Roberto Bonvallet

2
Esto hace que [], {}etc. den el mismo resultado que None, lo que no se desea. xstr(False), en particular, debe ser en "False"lugar de "". Abusar de lambdas es un mal ejemplo, use def xstr(s): return s or ""si desea mantenerlo todo en una línea.

55
Tenga en cuenta que califiqué mi respuesta desde el principio con "Si sabe que el valor siempre será una cadena o Ninguno".
Vinay Sajip

59

return s or '' ¡funcionará bien para su problema declarado!


44
A tener en cuenta que esto va a dar un resultado diferente para cuando s es 0 o falso (que no es la cuestión cadena original, pero el actualizado.)
Oddthinking

@Oddthinking s = Falseo s = 0probablemente sería un caso marginal en su uso y podría mitigarse fácilmente escribiéndolo comoreturn str(s or '')
Willem van Ketwich,

@WillemvanKetwich: Eso tiene exactamente el mismo problema: s (False) debería devolver 'False', no ''. s (0) debería devolver '0', no ''. Del mismo modo para un objeto que define __bool__ o __nonzero__.
Pensamiento extraño

@Oddthinking veo tu punto. En cualquier caso, si se usa exclusivamente para objetos de cadena como en la pregunta del OP, no debería ser un problema.
Willem van Ketwich

@WillemvanKetwich: Eche un vistazo a la pregunta actualizada y la advertencia en mi comentario - esto ha sido cubierto,
Pensamiento extraño

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

44
Esto devuelve ''para 0, [], {}, Falsey falsos como los valores, que no es lo que pidió el cartel.
StvnW

1
simplemente ponga str ([...]) alrededor de s: def xstr(s): return str(s) or ""
Federico Simonetta

8

Forma funcional (una línea)

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

1
"def xstr (s): return '' si s es None s s" también es un en línea, python no es tan estricto con espacios en blanco después de todo
SilentGhost

2
No es una frase real, solo está escrita en una línea g
Dario

1
¿en qué sentido no es un real en línea? consulte a su intérprete; no es un error de sintaxis. para todos los efectos es muy real que lambda ^ _ ^
SilentGhost

2
PEP 8 especies que debe usar def en lugar de asignar lambda a una variable. La única ventaja real de lambda es que puede escribir como parte de una expresión (pasando a otra función, por ejemplo) y esa ventaja se pierde en un código como este. Solía ​​hacer esto también, hasta que me di cuenta de que def se puede escribir en una línea, y luego PEP 8 me mostró el camino a seguir. SIEMPRE sigue a los dioses pitón.
Chico

8

Una buena frase para hacer esta construcción en algunas de las otras respuestas:

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

o incluso solo:

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

¿Por qué incluso mencionarlo (lambda v: v or '')?
Tvde1

Por qué no? ¡2 consejos por el precio de 1! 😀
Willem van Ketwich

1
Tenga en cuenta que una Falselista vacía también se convertirá en ''.
Nik O'Lai

lo mismo para 0, etc.
Walter Tross

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

Creo que es bastante pitónico, ¿qué tal este: "xstr = lambda s: {Ninguno: ''}. Get (s, s)" - reduce todo a una sola línea.
Juergen

14
Innecesariamente lento (construcción y búsqueda de dict extra) y más difícil de leer. Bastante poco pitón.
Tríptico

Tienes razón. Es bastante peligroso pero evita un salto condicional en el código de bytes de Python.
tobidope

44
La llamada a la función get () implica al menos un salto condicional adicional.
Tríptico

1
No podría decir qué debería hacer esto sin conocer la pregunta o mirar hacia arriba get.
Dario

5

Yo uso la función max:

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

Funciona como un encanto;) Simplemente ponga su cadena en el primer parámetro de la función.


55
Esto funciona porque 'str'> 'NoneType', y es específico de CPython. Del manual : "Los objetos de diferentes tipos, excepto los números, están ordenados por sus nombres de tipo". Además, esto no funcionará en Python 3000, ya que ya no se permite la comparación entre tipos (TypeError: tipos no ordenados: str ()> NoneType ()). Consulte ¿Cómo compara Python string e int?
plok

Es bueno saber gracias, así que no es una buena idea seguir adelante con el código compatible con Python 3.x.
radtek

4

Variación sobre lo anterior si necesita ser compatible con Python 2.4

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

2

Si se trata de formatear cadenas, puede hacer lo siguiente:

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))

55
Esto devolverá una cadena vacía para todos los valores falsos, que no es lo que solicitó el póster.
Tríptico

1

Siempre podemos evitar la conversión de tipos en los escenarios que se explican a continuación.

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

En el ejemplo anterior, en caso de que el valor del cliente variable sea Ninguno, se convierte más cuando se le asigna 'nombre'. La comparación en la cláusula 'if' siempre fallará.

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)

El ejemplo anterior funcionará correctamente. Tales escenarios son muy comunes cuando los valores se obtienen de URL, JSON o XML o incluso los valores necesitan una conversión de tipo adicional para cualquier manipulación.


0

Utilice la evaluación de cortocircuito:

s = a or '' + b or ''

Dado que + no es una muy buena operación en cadenas, mejor use cadenas de formato:

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

2
Esto también convertirá 'a' en cadenas vacías para todos los valores falsos, no solo Ninguno. Por ejemplo, las tuplas, listas y dictos vacíos se convertirán en cadenas vacías, que no es lo que especificó el OP.
Tríptico

+Es un operador perfectamente bueno para dos cadenas. Cuando intentas usarlo para unirte a docenas, tienes problemas. Para dos, probablemente será más rápido que otras opciones; De cualquier manera, está en el ruido.
kquinn

+1 para mí porque esto es exactamente lo que necesito en mi caso: lambda o función para reemplazar un solo operador ( or) me parece un poco exagerado ... No tengo casos de otros valores falsos, ya sea str o None. Aparte del comentario sobre el +operador, que podría depender de un escenario específico y podría necesitar una evaluación comparativa, esta respuesta no merece un -1
urbano

-3

Use la cadena F si está usando Python v3.7

xstr = F"{s}"

1
Esto está mal y devuelve la cadena 'None'si ses así None.
Lawrence
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.