En C # hay un operador de fusión nula (escrito como ??
) que permite una verificación nula fácil (corta) durante la asignación:
string s = null;
var other = s ?? "some default value";
¿Hay un pitón equivalente?
Sé que puedo hacer:
s = None
other = s if s else "some default value"
¿Pero hay una forma aún más corta (donde no necesito repetir s
)?
python
null-coalescing-operator
Klaus Byskov Pedersen
fuente
fuente
??
operador se propone como PEP 505 .Respuestas:
Ok, hay que aclarar cómo
or
operador. Es un operador booleano, por lo que funciona en un contexto booleano. Si los valores no son booleanos, se convierten a booleanos para los fines del operador.Tenga en cuenta que el
or
operador no regresa soloTrue
oFalse
. En cambio, devuelve el primer operando si el primer operando se evalúa como verdadero, y devuelve el segundo operando si el primer operando se evalúa como falso.En este caso, la expresión
x or y
devuelvex
si esTrue
o se evalúa como verdadera cuando se convierte en booleana. De lo contrario, vuelvey
. Para la mayoría de los casos, esto servirá para el mismo propósito del operador de fusión nula de C♯, pero tenga en cuenta:Si usa su variable
s
para contener algo que sea una referencia a la instancia de una clase oNone
(siempre que su clase no defina miembros__nonzero__()
y__len__()
), es seguro usar la misma semántica que el operador de fusión nula.De hecho, incluso puede ser útil tener este efecto secundario de Python. Como sabe qué valores se evalúan como falsos, puede usar esto para activar el valor predeterminado sin usar
None
específicamente (un objeto de error, por ejemplo).En algunos idiomas, este comportamiento se conoce como el operador de Elvis .
fuente
s
es un valor válido pero no es verdadero? (No sé Python, así que no estoy seguro de si el concepto de 'Truthy' se aplica.)None
y los contenedores vacíos (incluidas las cadenas) se consideran falsos, además de la constanteFalse
. Casi todo lo demás se considera cierto. Diría que el peligro principal aquí sería que obtendría un valor verdadero pero no de cadena, pero eso no será un problema en algunos programas.datetime.time(0)
también era falso!Estrictamente,
De lo contrario,
s = False
se convertirá"default value"
, lo que puede no ser lo que se pretendía.Si quieres acortar esto, prueba:
fuente
Consider x()?.y()?.z()
Aquí hay una función que devolverá el primer argumento que no es
None
:reduce()
podría iterar innecesariamente sobre todos los argumentos, incluso si el primer argumento noNone
lo es , por lo que también puede usar esta versión:fuente
def coalesce(*arg): return next((a for a in arg if a is not None), None)
hace lo mismo que su último ejemplo en una línea.Consider x()?.y()?.z()
Me doy cuenta de que esto se responde, pero hay otra opción cuando se trata de objetos.
Si tiene un objeto que podría ser:
Puedes usar:
Me gusta:
Al agregar
{}
como valor predeterminado, si falta "nombre", se devuelve un objeto vacío y se pasa al siguiente get. Esto es similar a null-safe-navigation en C #, que sería comoobj?.name?.first
.fuente
.get
, esto solo funciona para objetos tipo dictgetattr()
también.get
on dict no usa el parámetro predeterminado si el valor es None pero usa el parámetro predeterminado si el valor no existe porque la clave no está en el dict.{'a': None}.get('a', 'I do not want None')
todavía te daráNone
como resultado.Además de la respuesta de Juliano sobre el comportamiento de "o": es "rápido"
Entonces, a veces puede ser un atajo útil para cosas como
fuente
Además de la respuesta de @Bothwells (que prefiero) para valores individuales, a fin de verificar la evaluación nula de los valores de retorno de la función, puede usar un nuevo operador de morsa (desde python3.8):
Por lo tanto, la
test
función no necesita ser evaluada dos veces (como ena = 2 if test() is None else test()
)fuente
En caso de que necesite anidar más de una operación de fusión nula como:
model?.data()?.first()
Este no es un problema fácil de resolver
or
. Tampoco se puede resolver con lo.get()
que requiere un tipo de diccionario o similar (y no se puede anidar de todos modos) ogetattr()
que arrojará una excepción cuando NoneType no tenga el atributo.El pip relevante que considera agregar una fusión nula al lenguaje es PEP 505 y la discusión relevante para el documento está en el hilo de python-ideas .
fuente
Respecto a las respuestas de @Hugh Bothwell, @mortehu y @glglgl.
Configurar el conjunto de datos para probar
Definir implementaciones
Hacer la función de prueba
Resultados en mac i7 @ 2.7Ghz usando python 2.7
Claramente el
not_none
función responde la pregunta del OP correctamente y maneja el problema de "falsedad". También es el más rápido y fácil de leer. Si aplica la lógica en muchos lugares, es claramente la mejor manera de hacerlo.Si tiene un problema en el que desea encontrar el primer valor no nulo en un iterable, entonces la respuesta de @ mortehu es el camino a seguir. Pero es una solución a un problema diferente al OP, aunque puede manejar parcialmente ese caso. No puede tomar un valor iterativo Y predeterminado. El último argumento sería el valor predeterminado devuelto, pero entonces no pasaría un iterable en ese caso y no es explícito que el último argumento sea un valor predeterminado.
Podrías hacerlo a continuación, pero igual lo usaría
not_null
para el caso de uso de valor único.fuente
Para aquellos como yo que tropezaron aquí en busca de una solución viable para este problema, cuando la variable podría estar indefinida, lo más cercano que tengo es:
Tenga en cuenta que se necesita una cadena cuando se registran globales, pero luego se utiliza la variable real cuando se verifica el valor.
Más información sobre la existencia de variables: ¿Cómo verifico si existe una variable?
fuente
(variablename or False) == True
es lo mismo quevariablename == True
si no puede encontrar el nombre dentro del diccionario, devolverá el valor predeterminado, si el nombre existe, agregará cualquier valor existente con 1.
espero que esto pueda ayudar
fuente
Las dos funciones a continuación me han resultado muy útiles cuando se trata con muchos casos de pruebas variables.
fuente