python - ukuu - si A vs vs A no es Ninguno:
update linux kernel itsfoss (12)
Puedo usar:
if A:
en lugar de
if A is not None:
El último parece tan detallado. ¿Hay una diferencia?
Como está escrito en PEP8 :
Las comparaciones con singletons como None siempre deben hacerse con ''is'' o ''is not'', nunca con los operadores de igualdad .
Además, tenga cuidado con escribir "si x" cuando realmente quiere decir "si x no es Ninguno" - por ejemplo, cuando se prueba si una variable o argumento que tiene por defecto Ninguno se estableció en algún otro valor. ¡El otro valor puede tener un tipo (como un contenedor) que podría ser falso en un contexto booleano!
Depende del contexto.
Uso if A:
cuando estoy esperando que A
sea un tipo de colección, y solo quiero ejecutar el bloque si la colección no está vacía. Esto le permite a la persona que llama pasar cualquier colección que tenga buen comportamiento, vacía o no, y hacer que haga lo que espero. También permite None
y False
para suprimir la ejecución del bloque, que a veces es conveniente para llamar al código.
OTOH, si espero que A
sea un objeto completamente arbitrario pero podría haber sido predeterminado en None
, entonces siempre uso if A is not None
, ya que el código de llamada podría haber pasado deliberadamente una referencia a una colección vacía, una cadena vacía o una Tipo numérico de 0 valores, o False
booleano, o alguna instancia de clase que resulta ser falsa en el contexto booleano.
Y, por otro lado, si espero que A
sea algo más específico (por ejemplo, una instancia de una clase a la que voy a llamar métodos), pero podría haber sido predeterminado a None
, y considero que la conversión booleana predeterminada es ser una propiedad de la clase. No me importa aplicarla en todas las subclases, luego usaré if A:
para salvar mis dedos, la terrible carga de escribir 12 caracteres adicionales.
El primero es más Pythonic (mejor código ideomático), pero no ejecutará el bloque si A es False (no None).
La declaración
if A:
llamará a A.__nonzero__()
(vea la documentación de nombres de métodos especiales ) y usará el valor de retorno de esa función. Aquí está el resumen:
object.__nonzero__(self)
Llamado para implementar pruebas de valor verdad y la operación incorporada
bool()
; debe devolverFalse
oTrue
, o sus enteros equivalentes0
o1
. Cuando este método no está definido, se__len__()
, si está definido, y el objeto se considera verdadero si su resultado es distinto de cero. Si una clase no define ni__len__()
ni__nonzero__()
, todas sus instancias se consideran verdaderas.
Por otra parte,
if A is not None:
compara solo la referencia A
con None
para ver si es igual o no.
La mayoría de las guías que he visto sugieren que debes usar
si A:
a menos que tenga una razón para ser más específico.
Hay algunas pequeñas diferencias. Hay valores distintos de None que devuelven False, por ejemplo, listas vacías, o 0, así que piense en qué es lo que realmente está probando.
Muchas funciones devuelven None si no hay resultados apropiados. Por ejemplo, el método .first()
una consulta SQLAlchemy devuelve None si no hubo filas en el resultado. Supongamos que está seleccionando un valor que podría devolver 0 y necesita saber si realmente es 0 o si la consulta no tuvo ningún resultado.
Una expresión común es otorgarle a la función o al argumento opcional de un método el valor predeterminado de Ninguno, y luego probar que ese valor sea Ninguno para ver si se especificó. Por ejemplo:
def spam(eggs=None):
if eggs is None:
eggs = retrievefromconfigfile()
comparar eso con:
def spam(eggs=None):
if not eggs:
eggs = retrievefromconfigfile()
En este último caso, ¿qué ocurre si llama al spam(0)
no spam(0)
o al spam([])
? La función detectaría (incorrectamente) que no había pasado un valor para los eggs
y calcularía un valor predeterminado para usted. Probablemente eso no es lo que quieres.
O imagine un método como "devolver la lista de transacciones para una cuenta determinada". Si la cuenta no existe, puede devolver None. Esto es diferente a devolver una lista vacía (lo que significaría que "esta cuenta existe pero no ha registrado transacciones").
Finalmente, volviendo a las cosas de la base de datos. Hay una gran diferencia entre NULL y una cadena vacía. Una cadena vacía generalmente dice "aquí hay un valor, y ese valor no es nada en absoluto". NULL dice "este valor no ha sido ingresado".
En cada uno de esos casos, querría usar if A is None
. Está comprobando un valor específico: ninguno, no solo "cualquier valor que ocurra para convertirlo en falso".
python> = 2.6,
si escribimos como
if A:
generará una advertencia como,
FutureWarning: El comportamiento de este método cambiará en futuras versiones. Utilice la prueba específica ''len (elem)'' o ''elem is not None'' en su lugar.
Entonces podemos usar
if A is not None:
si A: resultará falso si A es 0, Falso o Ninguno, lo que puede generar resultados no deseados.
test.py
un archivo llamado test.py
y lo ejecuté en el intérprete. Puede cambiar lo que quiera para comprobar con seguridad cómo van las cosas detrás de escena.
import dis
def func1():
matchesIterator = None
if matchesIterator:
print( "On if." );
def func2():
matchesIterator = None
if matchesIterator is not None:
print( "On if." );
print( "/nFunction 1" );
dis.dis(func1)
print( "/nFunction 2" );
dis.dis(func2)
Esta es la diferencia de ensamblador:
Fuente:
>>> import importlib
>>> reload( test )
Function 1
6 0 LOAD_CONST 0 (None)
3 STORE_FAST 0 (matchesIterator)
8 6 LOAD_FAST 0 (matchesIterator)
9 POP_JUMP_IF_FALSE 20
10 12 LOAD_CONST 1 (''On if.'')
15 PRINT_ITEM
16 PRINT_NEWLINE
17 JUMP_FORWARD 0 (to 20)
>> 20 LOAD_CONST 0 (None)
23 RETURN_VALUE
Function 2
14 0 LOAD_CONST 0 (None)
3 STORE_FAST 0 (matchesIterator)
16 6 LOAD_FAST 0 (matchesIterator)
9 LOAD_CONST 0 (None)
12 COMPARE_OP 9 (is not)
15 POP_JUMP_IF_FALSE 26
18 18 LOAD_CONST 1 (''On if.'')
21 PRINT_ITEM
22 PRINT_NEWLINE
23 JUMP_FORWARD 0 (to 26)
>> 26 LOAD_CONST 0 (None)
29 RETURN_VALUE
<module ''test'' from ''test.py''>
Ellos hacen cosas muy diferentes .
El siguiente verifica si A tiene algo excepto los valores False
, []
, None
, ''''
y 0
. Comprueba el valor de A.
if A:
El siguiente verifica si A es un objeto diferente de Ninguno. Comprueba y compara la referencia (dirección de memoria) de A y Ninguno.
if A is not None:
ACTUALIZACIÓN: explicación adicional
Muchas veces los dos parecen hacer lo mismo, por lo que mucha gente los usa indistintamente, esa es una muy mala idea. La razón por la que los dos dan los mismos resultados es muchas veces por pura coincidencia debido a las optimizaciones del intérprete / compilador como el interning u otra cosa.
Con esas optimizaciones en mente, los enteros y las cadenas del mismo valor terminan usando el mismo espacio de memoria. Eso probablemente explica por qué dos cadenas separadas actúan como si fueran iguales.
> a = ''test''
> b = ''test''
> a is b
True
> a == b
True
Otras cosas no se comportan igual aunque ..
> a = []
> b = []
> a is b
False
> a == b
True
Las dos listas claramente tienen su propia memoria. Sorprendentemente, las tuplas se comportan como cadenas.
> a = ()
> b = ()
> a is b
True
> a == b
True
Probablemente esto se deba a que se garantiza que las tuplas no cambien, por lo tanto, tiene sentido reutilizar la misma memoria.
En pocas palabras, esto es que no puedes confiar en las coincidencias . El hecho de que grazna como un pato no significa que sea un pato. El uso is
y ==
dependiendo de lo que realmente desee verificar. Estas cosas pueden ser difíciles de depurar, ya que is
lee como una prosa que a menudo solo le damos un vistazo.
Ninguno es un valor especial en Python que generalmente designa una variable no inicializada. Para probar si A no tiene este valor particular, usa:
if A is not None
Los valores de Falsey son una clase especial de objetos en Python (por ejemplo, falso, []). Para probar si A es falsey uso:
if not A
Por lo tanto, las dos expresiones no son lo mismo Y será mejor que no las trate como sinónimos.
PS None también es falsey, por lo que la primera expresión implica la segunda. Pero el segundo cubre otros valores de Falsey además de None. Ahora ... si puedes estar seguro de que no puedes tener otros valores de falsey además de None en A, entonces puedes reemplazar la primera expresión por la segunda.
if x: #x is treated True except for all empty data types [],{},(),'''',0 False, and None
entonces no es lo mismo que
if x is not None # which works only on None