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)
Mark Harrison
fuente
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)
Tríptico
fuente
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)
SilentGhost
fuente
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.

dorvak
fuente
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) # -> ''
Vinay Sajip
fuente
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!

Alex Martelli
fuente
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 ""
Krystian Cybulski
fuente
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
Darío
fuente
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 '')
Willem van Ketwich
fuente
¿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)
tobidope
fuente
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.

radtek
fuente
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 ''
Peter Ericson
fuente
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)
maciek
fuente
1
def xstr(s):
    return s if s else ''

s = "%s%s" % (xstr(a), xstr(b))
phillc
fuente
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.

Sonda Pralhad Narsinh
fuente
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 '')
Sharjeel
fuente
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}"
usuario781486
fuente
1
Esto está mal y devuelve la cadena 'None'si ses así None.
Lawrence