En general, 'someobj is None' es preferible a 'someobj == None'
Aaron Maenpaa
¿Qué pasa con el pseudocódigo si X no es Ninguno? O X != None?
Charlie Parker, el
esta pregunta es más detallada que las otras ... felicitaciones ...
alamin
Respuestas:
187
En la primera prueba, Python intenta convertir el objeto a un boolvalor si aún no lo es. Aproximadamente, le preguntamos al objeto: ¿tiene sentido o no? Esto se hace usando el siguiente algoritmo:
Si el objeto tiene un __nonzero__método especial (como los incorporados numéricos, inty float), llama a este método. Debe devolver un boolvalor que luego se usa directamente, o un intvalor que se considera Falsesi es igual a cero.
De lo contrario, si el objeto tiene un __len__método especial (al igual que los contenedores empotrados, list, dict, set, tuple, ...), se llama a este método, teniendo en cuenta un contenedor Falsesi está vacío (longitud es cero).
De lo contrario, se considera el objeto a Truemenos que sea Noneen cuyo caso, se considera False.
En la segunda prueba, el objeto se compara por igualdad con None. Aquí, le preguntamos al objeto: "¿Eres igual a este otro valor?" Esto se hace usando el siguiente algoritmo:
Si el objeto tiene un __eq__método, se llama y el valor de retorno se convierte en un boolvalor y se utiliza para determinar el resultado de if.
De lo contrario, si el objeto tiene un __cmp__método, se llama. Esta función debe devolver una intindicación del orden de los dos objetos ( -1if self < other, 0if self == other, +1if self > other).
De lo contrario, los objetos se comparan por identidad (es decir, son referencias al mismo objeto, como puede ser probado por el isoperador).
Hay otra prueba posible usando el isoperador. Le estaríamos preguntando al objeto: "¿Eres este objeto en particular?"
En general, recomendaría usar la primera prueba con valores no numéricos, para usar la prueba de igualdad cuando desee comparar objetos de la misma naturaleza (dos cadenas, dos números, ...) y verificar la identidad solo cuando usando valores centinela (es Nonedecir, no inicializado para un campo miembro por ejemplo, o cuando se usan getattrlos __getitem__métodos o ).
Aunque técnicamente correcto, esto no explica que las tuplas, listas, dictos, strs, unicodes, ints, flotantes, etc. tengan un valor distinto de cero . Es mucho más común confiar en el valor de verdad del tipo incorporado que confiar en un método personalizado distinto de cero .
ddaa
50
Estas son en realidad ambas malas prácticas. Érase una vez, se consideró correcto tratar casualmente None y False como similares. Sin embargo, desde Python 2.2 esta no es la mejor política.
En primer lugar, cuando se hace una if xo if not xtipo de prueba, Python tiene para convertir implícitamente xa booleano. Las reglas para la boolfunción describen una serie de cosas que son falsas; todo lo demás es verdad. Si el valor de x no era adecuadamente booleano para empezar, esta conversión implícita no es realmente la forma más clara de decir las cosas.
Antes de Python 2.2, no había una función bool, por lo que era aún menos clara.
En segundo lugar, no deberías probar con == None. Deberías usar is Noney is not None.
-Comparisons to singletons like None should always be done with'is'or'is not', never the equality operators.Also, beware of writing "if x" when you really mean "if x is not None"-- e.g. when testing whether a variable or argument that defaults to
None was set to some other value.The other value might have a type
(such as a container) that could be false in a boolean context!
¿Cuántos singletons hay? Cinco: None, True, False, NotImplementedy Ellipsis. Dado que es muy poco probable que use NotImplementedo Ellipsis, y nunca diría if x is True(porque simplemente if xes mucho más claro), solo lo probará None.
La segunda forma categóricamente no es una mala práctica. PEP 8 recomienda usar if x dos veces . Primero para secuencias (en lugar de usar len) y luego para Verdadero y Falso (en lugar de usar is). Prácticamente todo el código Python que he visto usa if x y si no x.
Antti Rasinen
35
Porque Noneno es lo único que se considera falso.
ifnotFalse:print"False is false."ifnot0:print"0 is false."ifnot[]:print"An empty list is false."ifnot():print"An empty tuple is false."ifnot{}:print"An empty dict is false."ifnot"":print"An empty string is false."
False, 0, (), [], {}Y ""son todas diferentes None, por lo que sus dos fragmentos de código son no equivalentes.
Además, considere lo siguiente:
>>>False==0True>>>False==()False
if object:No es un control de igualdad. 0, (), [], None, {}, Etc son todas diferentes entre sí, pero todos ellos evalúan como False.
Esta es la "magia" detrás de expresiones de cortocircuito como:
Y ambos incorrectos porque "" es falso. El segundo debería leer '("",) o ("s",)'. De todos modos, las versiones modernas de python tienen un operador ternario adecuado. Este truco propenso a errores debe ser desterrado.
Se llama al método __nonzero__ de spam . Del manual de Python:
__nonzero__ ( self ) Llamado para implementar pruebas de valor de verdad y la operación incorporada bool (); debe devolver False o True, o sus equivalentes enteros 0 o 1. Cuando este método no está definido, se llama a __len __ (), si está definido (ver más abajo). Si una clase no define __len __ () ni __nonzero __ (), todas sus instancias se consideran verdaderas.
Si preguntas
if spam ==None:print"Sorry. No SPAM here either."
la __eq__ método de correo no deseado es llamado con el argumento Ninguno .
Estas dos comparaciones tienen diferentes propósitos. El primero verifica el valor booleano de algo, el segundo verifica la identidad con el valor Ninguno.
Para ser absolutamente correcto, el segundo verifica la igualdad con un valor None ... "someobj is None" verifica la identidad.
Matthew Trevor
0
Por un lado, el primer ejemplo es más corto y se ve mejor. Según las otras publicaciones, lo que elijas también depende de lo que realmente quieras hacer con la comparación.
Personalmente, elegí un enfoque coherente en todos los idiomas: lo hago if (var)(o equivalente) solo si var se declara como booleano (o se define como tal, en C no tenemos un tipo específico). Incluso prefijo estas variables con un b(por lo que sería en bVarrealidad) para asegurarme de que no usaré accidentalmente otro tipo aquí.
Realmente no me gusta el casting implícito a booleano, mucho menos cuando hay numerosas reglas complejas.
Por supuesto, la gente no estará de acuerdo. Algunos van más allá, veo if (bVar == true)en el código de Java en mi trabajo (¡demasiado redundante para mi gusto!), A otros les encanta la sintaxis compacta, ir while (line = getNextLine())(demasiado ambiguo para mí).
X != None
?Respuestas:
En la primera prueba, Python intenta convertir el objeto a un
bool
valor si aún no lo es. Aproximadamente, le preguntamos al objeto: ¿tiene sentido o no? Esto se hace usando el siguiente algoritmo:Si el objeto tiene un
__nonzero__
método especial (como los incorporados numéricos,int
yfloat
), llama a este método. Debe devolver unbool
valor que luego se usa directamente, o unint
valor que se consideraFalse
si es igual a cero.De lo contrario, si el objeto tiene un
__len__
método especial (al igual que los contenedores empotrados,list
,dict
,set
,tuple
, ...), se llama a este método, teniendo en cuenta un contenedorFalse
si está vacío (longitud es cero).De lo contrario, se considera el objeto a
True
menos que seaNone
en cuyo caso, se consideraFalse
.En la segunda prueba, el objeto se compara por igualdad con
None
. Aquí, le preguntamos al objeto: "¿Eres igual a este otro valor?" Esto se hace usando el siguiente algoritmo:Si el objeto tiene un
__eq__
método, se llama y el valor de retorno se convierte en unbool
valor y se utiliza para determinar el resultado deif
.De lo contrario, si el objeto tiene un
__cmp__
método, se llama. Esta función debe devolver unaint
indicación del orden de los dos objetos (-1
ifself < other
,0
ifself == other
,+1
ifself > other
).De lo contrario, los objetos se comparan por identidad (es decir, son referencias al mismo objeto, como puede ser probado por el
is
operador).Hay otra prueba posible usando el
is
operador. Le estaríamos preguntando al objeto: "¿Eres este objeto en particular?"En general, recomendaría usar la primera prueba con valores no numéricos, para usar la prueba de igualdad cuando desee comparar objetos de la misma naturaleza (dos cadenas, dos números, ...) y verificar la identidad solo cuando usando valores centinela (es
None
decir, no inicializado para un campo miembro por ejemplo, o cuando se usangetattr
los__getitem__
métodos o ).Para resumir, tenemos:
fuente
Estas son en realidad ambas malas prácticas. Érase una vez, se consideró correcto tratar casualmente None y False como similares. Sin embargo, desde Python 2.2 esta no es la mejor política.
En primer lugar, cuando se hace una
if x
oif not x
tipo de prueba, Python tiene para convertir implícitamentex
a booleano. Las reglas para labool
función describen una serie de cosas que son falsas; todo lo demás es verdad. Si el valor de x no era adecuadamente booleano para empezar, esta conversión implícita no es realmente la forma más clara de decir las cosas.Antes de Python 2.2, no había una función bool, por lo que era aún menos clara.
En segundo lugar, no deberías probar con
== None
. Deberías usaris None
yis not None
.Consulte PEP 8, Guía de estilo para el código Python .
¿Cuántos singletons hay? Cinco:
None
,True
,False
,NotImplemented
yEllipsis
. Dado que es muy poco probable que useNotImplemented
oEllipsis
, y nunca diríaif x is True
(porque simplementeif x
es mucho más claro), solo lo probaráNone
.fuente
Porque
None
no es lo único que se considera falso.False
,0
,()
,[]
,{}
Y""
son todas diferentesNone
, por lo que sus dos fragmentos de código son no equivalentes.Además, considere lo siguiente:
if object:
No es un control de igualdad.0
,()
,[]
,None
,{}
, Etc son todas diferentes entre sí, pero todos ellos evalúan como False.Esta es la "magia" detrás de expresiones de cortocircuito como:
que es la abreviatura de:
aunque realmente deberías escribir:
fuente
PEP 8: la guía de estilo para el código Python recomienda usar es o no si está probando la ausencia de ninguno
Por otro lado, si está probando más de None-ness, debe utilizar el operador booleano
fuente
Si preguntas
Se llama al método __nonzero__ de spam . Del manual de Python:
Si preguntas
la __eq__ método de correo no deseado es llamado con el argumento Ninguno .
Para obtener más información sobre las posibilidades de personalización, consulte la documentación de Python en https://docs.python.org/reference/datamodel.html#basic-customization
fuente
Estas dos comparaciones tienen diferentes propósitos. El primero verifica el valor booleano de algo, el segundo verifica la identidad con el valor Ninguno.
fuente
Por un lado, el primer ejemplo es más corto y se ve mejor. Según las otras publicaciones, lo que elijas también depende de lo que realmente quieras hacer con la comparación.
fuente
La respuesta es, depende".
Utilizo el primer ejemplo si considero que 0, "", [] y False (la lista no es exhaustiva) son equivalentes a None en este contexto.
fuente
Personalmente, elegí un enfoque coherente en todos los idiomas: lo hago
if (var)
(o equivalente) solo si var se declara como booleano (o se define como tal, en C no tenemos un tipo específico). Incluso prefijo estas variables con unb
(por lo que sería enbVar
realidad) para asegurarme de que no usaré accidentalmente otro tipo aquí.Realmente no me gusta el casting implícito a booleano, mucho menos cuando hay numerosas reglas complejas.
Por supuesto, la gente no estará de acuerdo. Algunos van más allá, veo
if (bVar == true)
en el código de Java en mi trabajo (¡demasiado redundante para mi gusto!), A otros les encanta la sintaxis compacta, irwhile (line = getNextLine())
(demasiado ambiguo para mí).fuente