python - sentencia - ¿Es seguro confiar en la orden de evaluación de condición en las declaraciones if?
sentencia if else en c++ (6)
Es perfectamente seguro y lo hago todo el tiempo.
¿Es una mala práctica usar el siguiente formato cuando my_var
puede ser None?
if my_var and ''something'' in my_var:
#do something
El problema es que ''something'' in my_var
lanzará un TypeError si my_var es None.
O debería usar:
if my_var:
if ''something'' in my_var:
#do something
o
try:
if ''something'' in my_var:
#do something
except TypeError:
pass
Para reformular la pregunta, ¿cuál de las anteriores es la mejor práctica en Python (si existe)?
¡Las alternativas son bienvenidas!
Es seguro depender del orden de los condicionales ( referencia de Python aquí ), específicamente debido al problema que usted señala: es muy útil poder realizar un cortocircuito en la evaluación que podría causar problemas en una serie de condicionales.
Este tipo de código aparece en la mayoría de los idiomas:
IF exists(variable) AND variable.doSomething()
THEN ...
Me gustaría ir con try / except, pero depende de lo que sepas sobre la variable.
Si espera que la variable exista la mayor parte del tiempo, entonces try / except es menos operaciones. Si espera que la variable sea None la mayor parte del tiempo, una instrucción IF será menos operaciones.
No es tan simple. Como tío C #, estoy muy acostumbrado a hacer algo como:
if(x != null && ! string.isnullorempty(x.Name))
{
//do something
}
Lo anterior funciona muy bien y se evalúa como se espera. Sin embargo, en VB.Net, lo siguiente produciría un resultado que NO esperabas:
If Not x Is Nothing **And** Not String.IsNullOrEmpty(x.Name) Then
''do something
End If
Lo anterior generará una excepción. La sintaxis correcta debe ser
If Not x Is Nothing **AndAlso** Not String.IsNullOrEmpty(x.Name) Then
''do something
End If
Tenga en cuenta la diferencia muy sutil. Esto me confundió durante unos 10 minutos (demasiado tiempo) y es por eso que C # (y otros) tipos deben tener mucho cuidado al codificar en otros idiomas.
Puede que esté siendo un poco pedante aquí, pero diría que la mejor respuesta es
if my_var is not None and ''something'' in my_var:
#do something
La diferencia es la comprobación explícita de None
, en lugar de la conversión implícita de my_var
a True
o False
.
Aunque estoy seguro de que en su caso la distinción no es importante, en el caso más general, sería bastante posible que la variable no sea None
pero aún así evalúe False
, por ejemplo, un valor entero de 0
o una lista vacía.
De manera contraria a la mayoría de las afirmaciones de otros carteles de que es seguro, diría que es seguro siempre y cuando seas explícito. Si no estás convencido, considera esta clase muy artificial:
class Contrived(object):
def __contains__(self, s):
return True
def __nonzero__(self):
return False
my_var = Contrived()
if ''something'' in my_var:
print "Yes the condition is true"
if my_var and ''something'' in my_var:
print "But this statement won''t get reached."
if my_var is not None and ''something'' in my_var:
print "Whereas this one will."
Sí, sé que no es un ejemplo realista, pero las variaciones sí ocurren en el código real, especialmente cuando None
se utiliza para indicar un argumento de función predeterminado.
Sí, es seguro, está explícita y muy claramente definido en la referencia del lenguaje:
La expresión
x and y
primero evalúax
; six
esfalse
, se devuelve su valor; de lo contrario,y
se evalúa y se devuelve el valor resultante.La expresión
x or y
primero primero evalúax
; six
es verdadero, se devuelve su valor; de lo contrario,y
se evalúa y se devuelve el valor resultante.