Y la razón para elegir egg is Nonemás egg == None: Estos últimos pueden ser sobrecargados, y es probable que se rompa cuando se comparan objeto válido con la opción Ninguno (depende de cómo se implementa, pero no esperan que todos tomen comparaciones con ninguno en cuenta, ¿verdad?) , mientras que issiempre funciona igual.
94
¿Por qué los diseñadores de Python no eligieron "nulo"? Solo tienes que ser diferente, ¿no? ;)
Vidar
35
@Vidar 'Ninguno' no es la falta de un objeto (como 'nulo' es, una referencia nula), es un objeto real. Nunca obtendrá un objeto 'Ninguno' que pase por un objeto que sea de un tipo que no sea 'NoneType'. Tampoco es un concepto de lenguaje. No está integrado en el lenguaje de Python, es parte de la biblioteca estándar de Python. Ninguno! == (ejem) Nulo
Rushyo
11
@ naught101 No serviría de nada; ya que no existe el concepto de punteros. Si está utilizando la biblioteca ctypes, None se usará como sinónimo de la dirección cero, pero todavía no hay un concepto de lenguaje de 'referencia nula'. En Python, siempre dejaste referenciando algún tipo de objeto, incluso si ese objeto es Ninguno. Sospecho que esto simplifica enormemente el lenguaje.
Rushyo
55
gran presentación explicando el 'error de mil millones de dólares' que es la referencia nula: infoq.com/presentations/… . Otras opciones en lugar de nulas son las opciones o los tipos tal vez (personalizados).
Michael Trouw
136
None, Python es nulo?
No hay nullen Python, en cambio hay None. Como ya se dijo, la forma más precisa de probar que algo se ha dado Nonecomo valor es usar el isoperador de identidad, que prueba que dos variables se refieren al mismo objeto.
Nonees la única instancia de la clase NoneTypey cualquier otro intento de instanciar esa clase devolverá el mismo objeto, lo que hace Noneun singleton. Los recién llegados a Python a menudo ven mensajes de error que mencionan NoneTypey se preguntan qué es. Es mi opinión personal que estos mensajes simplemente podrían mencionarse Nonepor su nombre porque, como veremos en breve, Nonedeja poco espacio para la ambigüedad. Entonces, si ve algún TypeErrormensaje que menciona que NoneTypeno puede hacer esto o no puede hacer eso, solo sepa que es simplemente el Noneque se estaba utilizando de una manera que no puede.
Además, Nonees una constante incorporada, tan pronto como inicie Python, estará disponible para usar desde cualquier lugar, ya sea en módulo, clase o función. NoneTypepor el contrario, no, primero debe obtener una referencia al consultar Nonesu clase.
>>>NoneTypeNameError: name 'NoneType'isnot defined>>> type(None)NoneType
Puede verificar Nonela singularidad con la función de identidad de Python id(). Devuelve el número único asignado a un objeto, cada objeto tiene uno. Si la identificación de dos variables es la misma, de hecho apuntan al mismo objeto.
En una versión mucho más antigua de Python (anterior a la 2.4), era posible reasignar None, pero ya no. Ni siquiera como un atributo de clase o en los confines de una función.
# In Python 2.7>>>classSomeClass(object):...def my_fnc(self):... self.None='foo'SyntaxError: cannot assign to None>>>def my_fnc():None='foo'SyntaxError: cannot assign to None# In Python 3.5>>>classSomeClass:...def my_fnc(self):... self.None='foo'SyntaxError: invalid syntax>>>def my_fnc():None='foo'SyntaxError: cannot assign to keyword
Por lo tanto, es seguro asumir que todas las Nonereferencias son iguales. No hay "costumbre" None.
Para probar el Noneuso del isoperador
Al escribir código, puede sentirse tentado a probar Noneness como este:
if value==None:pass
O para probar la falsedad como esta
ifnot value:pass
Debe comprender las implicaciones y por qué a menudo es una buena idea ser explícito.
Caso 1: probar si un valor es None
porque hacer esto
value isNone
más bien que
value==None
El primero es equivalente a:
id(value)==id(None)
Mientras que la expresión value==Nonede hecho se aplica así
value.__eq__(None)
Si el valor es realmente None, obtendrá lo que esperaba.
En los casos más comunes, el resultado será el mismo, pero el __eq__()método abre una puerta que anula cualquier garantía de precisión, ya que se puede anular en una clase para proporcionar un comportamiento especial.
Considera esta clase.
>>>classEmpty(object):...def __eq__(self, other):...returnnot other
Entonces lo pruebas Noney funciona
>>> empty =Empty()>>> empty==NoneTrue
Pero luego también funciona en la cadena vacía
>>> empty==''True
Y todavía
>>>''==NoneFalse>>> empty isNoneFalse
Caso 2: uso Nonecomo un booleano
Las siguientes dos pruebas
if value:# do somethingifnot value:# do something
de hecho son evaluados como
if bool(value):# do somethingifnot bool(value):# do something
Nonees una "falsey", lo que significa que si se convierte en booleano, volverá Falsey, si se aplica, el notoperador volverá True. Sin embargo, tenga en cuenta que no es una propiedad exclusiva de None. Además de Falsesí mismo, la propiedad se comparte mediante listas vacías, tuplas, conjuntos, dictados, cadenas, así como 0, y todos los objetos de las clases que implementan el __bool__()método mágico para devolver False.
>>> bool(None)False>>>notNoneTrue>>> bool([])False>>>not[]True>>>classMyFalsey(object):...def __bool__(self):...returnFalse>>> f =MyFalsey()>>> bool(f)False>>>not fTrue
Por lo tanto, cuando pruebe las variables de la siguiente manera, tenga más en cuenta lo que está incluyendo o excluyendo de la prueba:
def some_function(value=None):ifnot value:
value = init_value()
En lo anterior, ¿quiso llamar init_value()cuando el valor se estableció específicamente en None, o quiso decir que un valor establecido en 0, o la cadena vacía, o una lista vacía también deberían activar la inicialización? Como dije, ten en cuenta. Como suele ser el caso en Python, explícito es mejor que implícito .
None en la práctica
None utilizado como valor de señal
Nonetiene un estado especial en Python. Es un valor de referencia favorito porque muchos algoritmos lo tratan como un valor excepcional. En tales escenarios, se puede usar como un indicador para indicar que una condición requiere un manejo especial (como la configuración de un valor predeterminado).
Puede asignar Nonea la palabra clave argumentos de una función y luego probarla explícitamente.
def my_function(value, param=None):if param isNone:# do something outrageous!
Puede devolverlo como predeterminado cuando intente acceder al atributo de un objeto y luego probarlo explícitamente antes de hacer algo especial.
value = getattr(some_obj,'some_attribute',None)if value isNone:# do something spectacular!
Por defecto, el get()método de un diccionario regresa Noneal intentar acceder a una clave no existente:
>>> some_dict ={}>>> value = some_dict.get('foo')>>> value isNoneTrue
Si intentara acceder a él utilizando la notación de subíndice KeyError, se generaría
>>> value = some_dict['foo']KeyError:'foo'
Del mismo modo, si intenta hacer estallar un elemento no existente
>>> value = some_dict.pop('foo')KeyError:'foo'
que puede suprimir con un valor predeterminado que generalmente se establece en None
value = some_dict.pop('foo',None)if value isNone:# booom!
None se utiliza como indicador y valor válido
Los usos descritos anteriormente se Noneaplican cuando no se considera un valor válido, sino más bien como una señal para hacer algo especial. Sin embargo, hay situaciones en las que a veces es importante saber de dónde Noneviene porque, aunque se usa como señal, también podría ser parte de los datos.
Cuando consulta un objeto para obtener su atributo con el getattr(some_obj, 'attribute_name', None)regreso, Noneno le dice si el atributo al que estaba intentando acceder estaba configurado Noneo si estaba completamente ausente del objeto. La misma situación al acceder a una clave de un diccionario some_dict.get('some_key'), como , no sabe si some_dict['some_key']falta o si está configurada en None. Si necesita esa información, la forma habitual de manejar esto es intentar acceder directamente al atributo o clave desde una try/exceptconstrucción:
try:# equivalent to getattr() without specifying a default# value = getattr(some_obj, 'some_attribute')
value = some_obj.some_attribute# now you handle `None` the data hereif value isNone:# do something here because the attribute was set to NoneexceptAttributeError:# we're now hanling the exceptional situation from here.# We could assign None as a default value if required.
value =None# In addition, since we now know that some_obj doesn't have the# attribute 'some_attribute' we could do something about that.
log_something(some_obj)
De manera similar con dict:
try:
value = some_dict['some_key']if value isNone:# do something here because 'some_key' is set to NoneexceptKeyError:# set a default
value =None# and do something because 'some_key' was missing# from the dict.
log_something(some_dict)
Los dos ejemplos anteriores muestran cómo manejar casos de objeto y diccionario, ¿qué pasa con las funciones? Lo mismo, pero usamos el argumento de palabra clave de doble asterisco para ese fin:
def my_function(**kwargs):try:
value = kwargs['some_key']if value isNone:# do something because 'some_key' is explicitly # set to NoneexceptKeyError:# we assign the default
value =None# and since it's not coming from the caller.
log_something('did not receive "some_key"')
None usado solo como un valor válido
Si encuentra que su código está lleno del try/exceptpatrón anterior simplemente para diferenciar entre Noneindicadores y Nonedatos, simplemente use otro valor de prueba. Hay un patrón en el que un valor que queda fuera del conjunto de valores válidos se inserta como parte de los datos en una estructura de datos y se usa para controlar y probar condiciones especiales (por ejemplo, límites, estado, etc.). Tal valor se llama centinela y se puede usar de la misma manera que Nonese usa como señal. Es trivial crear un centinela en Python.
undefined = object()
El undefinedobjeto anterior es único y no hace mucho de nada que pueda ser de interés para un programa, por lo tanto, es un excelente reemplazo Nonecomo indicador. Se aplican algunas advertencias, más sobre eso después del código.
Con función
def my_function(value, param1=undefined, param2=undefined):if param1 is undefined:# we know nothing was passed to it, not even None
log_something('param1 was missing')
param1 =Noneif param2 is undefined:# we got nothing here either
log_something('param2 was missing')
param2 =None
Con dict
value = some_dict.get('some_key', undefined)if value isNone:
log_something("'some_key' was set to None")if value is undefined:# we know that the dict didn't have 'some_key'
log_something("'some_key' was not set at all")
value =None
Con un objeto
value = getattr(obj,'some_attribute', undefined)if value isNone:
log_something("'obj.some_attribute' was set to None")if value is undefined:# we know that there's no obj.some_attribute
log_something("no 'some_attribute' set on obj")
value =None
Como mencioné anteriormente, los centinelas personalizados vienen con algunas advertencias. Primero, no son palabras clave como None, por lo que Python no las protege. Puede sobrescribir lo undefinedanterior en cualquier momento, en cualquier lugar del módulo que esté definido, así que tenga cuidado de cómo los expone y usa. A continuación, la instancia devuelta por object()no es un singleton, si realiza esa llamada 10 veces obtendrá 10 objetos diferentes. Finalmente, el uso de un centinela es altamente idiosincrásico. Un centinela es específico de la biblioteca en la que se usa y, como tal, su alcance generalmente debe limitarse a los elementos internos de la biblioteca. No debería "filtrarse". El código externo solo debe ser consciente de él, si su propósito es extender o complementar la API de la biblioteca.
Ah, entonces IIUC que usualmente terminará llamando cosas .__ eq__? En ese caso me retracto de mi sugerencia.
hkBst
@MichaelEkoka puede compartir la fuente de esta información impresionante y útil.
Anidhya Bhatnagar
Práctica estándar. Puede encontrar algunos indicios al seguir el tutorial de Python , pero leer el código fuente de los proyectos populares es mi consejo número uno para sumergirse rápidamente en Python idiomático .
Michael Ekoka
67
No se llama nulo como en otros idiomas, pero None. Siempre hay una sola instancia de este objeto, por lo que puede verificar la equivalencia con x is None(comparación de identidad) en lugar de x == None, si lo desea.
Voy a encontrar una manera de romper Python volviendo a crear instancias None. ¡Entonces todas esas personas inteligentes que se compararon contra NoneTypetriunfarán!
Zenexer
28
En Python, para representar la ausencia de un valor, puede usar el valor None ( types.NoneType.None ) para objetos y "" (o len () == 0 ) para cadenas. Por lo tanto:
if yourObject isNone:# if yourObject == None:...if yourString =="":# if yourString.len() == 0:...
En cuanto a la diferencia entre "==" y "es", la prueba de identidad de objeto usando "==" debería ser suficiente. Sin embargo, dado que la operación "es" se define como la operación de identidad de objeto, probablemente sea más correcto usarla, en lugar de "==". No estoy seguro si hay incluso una diferencia de velocidad.
Hasta donde yo sé, (0 == falso) devuelve verdadero EN CADA lenguaje de programación. Esto se debe a que falso está codificado como 0 y "verdadero" como todo lo que NO es 0. Sin embargo, no es que el operador "es" no sea el mismo que el "==". Esta es más o menos la misma diferencia entre "==" y "igual" en Java. ¡El operador "es", de hecho, comprueba si DOS OBJETOS son iguales (la misma instancia y NO el mismo contenido)!
Paolo Rovelli
12
Paolo, para su información, (0 == falso) no devuelve verdadero en todos los lenguajes de programación. Un ejemplo de contador rápido sería Scala, donde (0 == falso) devuelve falso, y estoy seguro de que Scala no es el único lenguaje de programación que devuelve falso al comparar un número con un booleano.
Rob Wilton
2
¡Ok lo tengo! Entonces, digamos en la mayoría de los lenguajes de programación.
Paolo Rovelli
3
En JavaScript, la razón 0 == falseregresa truees porque el operador de doble igualdad escribe coerción. Sin embargo, con el operador triple-igual, 0 === falsedevuelve false, porque 'número' y 'booleano' son tipos diferentes.
jkdev
1
@PaoloRovelli, en Lua, Ruby y Clojure, 0 se trata como trueen condicionales. En Rust and Go, 0y false son diferentes tipos que no se pueden comparar para la igualdad.
scooter-cuelga el
0
Nulo es un tipo de objeto especial como:
>>>type(None)<class'NoneType'>
Puede verificar si un objeto está en la clase 'NoneType':
No, no lo hará. Esa expresión volverá Truepara cualquier valor Falsy, no sólo None.
insert_name_here
Es cierto, y el simple "si no foo:" no respondería correctamente la pregunta original, como se indicó. Sin embargo, python se escribe dinámicamente e invita a reducir los protocolos de sintaxis, por lo que me parece válido considerar construcciones más simples y similares.
egg is None
másegg == None
: Estos últimos pueden ser sobrecargados, y es probable que se rompa cuando se comparan objeto válido con la opción Ninguno (depende de cómo se implementa, pero no esperan que todos tomen comparaciones con ninguno en cuenta, ¿verdad?) , mientras queis
siempre funciona igual.None
, Python es nulo?No hay
null
en Python, en cambio hayNone
. Como ya se dijo, la forma más precisa de probar que algo se ha dadoNone
como valor es usar elis
operador de identidad, que prueba que dos variables se refieren al mismo objeto.Los basicos
Hay y solo puede haber uno
None
None
es la única instancia de la claseNoneType
y cualquier otro intento de instanciar esa clase devolverá el mismo objeto, lo que haceNone
un singleton. Los recién llegados a Python a menudo ven mensajes de error que mencionanNoneType
y se preguntan qué es. Es mi opinión personal que estos mensajes simplemente podrían mencionarseNone
por su nombre porque, como veremos en breve,None
deja poco espacio para la ambigüedad. Entonces, si ve algúnTypeError
mensaje que menciona queNoneType
no puede hacer esto o no puede hacer eso, solo sepa que es simplemente elNone
que se estaba utilizando de una manera que no puede.Además,
None
es una constante incorporada, tan pronto como inicie Python, estará disponible para usar desde cualquier lugar, ya sea en módulo, clase o función.NoneType
por el contrario, no, primero debe obtener una referencia al consultarNone
su clase.Puede verificar
None
la singularidad con la función de identidad de Pythonid()
. Devuelve el número único asignado a un objeto, cada objeto tiene uno. Si la identificación de dos variables es la misma, de hecho apuntan al mismo objeto.None
no se puede sobrescribirEn una versión mucho más antigua de Python (anterior a la 2.4), era posible reasignar
None
, pero ya no. Ni siquiera como un atributo de clase o en los confines de una función.Por lo tanto, es seguro asumir que todas las
None
referencias son iguales. No hay "costumbre"None
.Para probar el
None
uso delis
operadorAl escribir código, puede sentirse tentado a probar Noneness como este:
O para probar la falsedad como esta
Debe comprender las implicaciones y por qué a menudo es una buena idea ser explícito.
Caso 1: probar si un valor es
None
porque hacer esto
más bien que
El primero es equivalente a:
Mientras que la expresión
value==None
de hecho se aplica asíSi el valor es realmente
None
, obtendrá lo que esperaba.En los casos más comunes, el resultado será el mismo, pero el
__eq__()
método abre una puerta que anula cualquier garantía de precisión, ya que se puede anular en una clase para proporcionar un comportamiento especial.Considera esta clase.
Entonces lo pruebas
None
y funcionaPero luego también funciona en la cadena vacía
Y todavía
Caso 2: uso
None
como un booleanoLas siguientes dos pruebas
de hecho son evaluados como
None
es una "falsey", lo que significa que si se convierte en booleano, volveráFalse
y, si se aplica, elnot
operador volveráTrue
. Sin embargo, tenga en cuenta que no es una propiedad exclusiva deNone
. Además deFalse
sí mismo, la propiedad se comparte mediante listas vacías, tuplas, conjuntos, dictados, cadenas, así como 0, y todos los objetos de las clases que implementan el__bool__()
método mágico para devolverFalse
.Por lo tanto, cuando pruebe las variables de la siguiente manera, tenga más en cuenta lo que está incluyendo o excluyendo de la prueba:
En lo anterior, ¿quiso llamar
init_value()
cuando el valor se estableció específicamente enNone
, o quiso decir que un valor establecido en0
, o la cadena vacía, o una lista vacía también deberían activar la inicialización? Como dije, ten en cuenta. Como suele ser el caso en Python, explícito es mejor que implícito .None
en la prácticaNone
utilizado como valor de señalNone
tiene un estado especial en Python. Es un valor de referencia favorito porque muchos algoritmos lo tratan como un valor excepcional. En tales escenarios, se puede usar como un indicador para indicar que una condición requiere un manejo especial (como la configuración de un valor predeterminado).Puede asignar
None
a la palabra clave argumentos de una función y luego probarla explícitamente.Puede devolverlo como predeterminado cuando intente acceder al atributo de un objeto y luego probarlo explícitamente antes de hacer algo especial.
Por defecto, el
get()
método de un diccionario regresaNone
al intentar acceder a una clave no existente:Si intentara acceder a él utilizando la notación de subíndice
KeyError
, se generaríaDel mismo modo, si intenta hacer estallar un elemento no existente
que puede suprimir con un valor predeterminado que generalmente se establece en
None
None
se utiliza como indicador y valor válidoLos usos descritos anteriormente se
None
aplican cuando no se considera un valor válido, sino más bien como una señal para hacer algo especial. Sin embargo, hay situaciones en las que a veces es importante saber de dóndeNone
viene porque, aunque se usa como señal, también podría ser parte de los datos.Cuando consulta un objeto para obtener su atributo con el
getattr(some_obj, 'attribute_name', None)
regreso,None
no le dice si el atributo al que estaba intentando acceder estaba configuradoNone
o si estaba completamente ausente del objeto. La misma situación al acceder a una clave de un diccionariosome_dict.get('some_key')
, como , no sabe sisome_dict['some_key']
falta o si está configurada enNone
. Si necesita esa información, la forma habitual de manejar esto es intentar acceder directamente al atributo o clave desde unatry/except
construcción:De manera similar con dict:
Los dos ejemplos anteriores muestran cómo manejar casos de objeto y diccionario, ¿qué pasa con las funciones? Lo mismo, pero usamos el argumento de palabra clave de doble asterisco para ese fin:
None
usado solo como un valor válidoSi encuentra que su código está lleno del
try/except
patrón anterior simplemente para diferenciar entreNone
indicadores yNone
datos, simplemente use otro valor de prueba. Hay un patrón en el que un valor que queda fuera del conjunto de valores válidos se inserta como parte de los datos en una estructura de datos y se usa para controlar y probar condiciones especiales (por ejemplo, límites, estado, etc.). Tal valor se llama centinela y se puede usar de la misma manera queNone
se usa como señal. Es trivial crear un centinela en Python.El
undefined
objeto anterior es único y no hace mucho de nada que pueda ser de interés para un programa, por lo tanto, es un excelente reemplazoNone
como indicador. Se aplican algunas advertencias, más sobre eso después del código.Con función
Con dict
Con un objeto
Como mencioné anteriormente, los centinelas personalizados vienen con algunas advertencias. Primero, no son palabras clave como
None
, por lo que Python no las protege. Puede sobrescribir loundefined
anterior en cualquier momento, en cualquier lugar del módulo que esté definido, así que tenga cuidado de cómo los expone y usa. A continuación, la instancia devuelta porobject()
no es un singleton, si realiza esa llamada 10 veces obtendrá 10 objetos diferentes. Finalmente, el uso de un centinela es altamente idiosincrásico. Un centinela es específico de la biblioteca en la que se usa y, como tal, su alcance generalmente debe limitarse a los elementos internos de la biblioteca. No debería "filtrarse". El código externo solo debe ser consciente de él, si su propósito es extender o complementar la API de la biblioteca.fuente
No se llama nulo como en otros idiomas, pero
None
. Siempre hay una sola instancia de este objeto, por lo que puede verificar la equivalencia conx is None
(comparación de identidad) en lugar dex == None
, si lo desea.fuente
None
. ¡Entonces todas esas personas inteligentes que se compararon contraNoneType
triunfarán!En Python, para representar la ausencia de un valor, puede usar el valor None ( types.NoneType.None ) para objetos y "" (o len () == 0 ) para cadenas. Por lo tanto:
En cuanto a la diferencia entre "==" y "es", la prueba de identidad de objeto usando "==" debería ser suficiente. Sin embargo, dado que la operación "es" se define como la operación de identidad de objeto, probablemente sea más correcto usarla, en lugar de "==". No estoy seguro si hay incluso una diferencia de velocidad.
De todos modos, puedes echar un vistazo a:
fuente
0 == false
regresatrue
es porque el operador de doble igualdad escribe coerción. Sin embargo, con el operador triple-igual,0 === false
devuelvefalse
, porque 'número' y 'booleano' son tipos diferentes.true
en condicionales. En Rust and Go,0
yfalse
son diferentes tipos que no se pueden comparar para la igualdad.Nulo es un tipo de objeto especial como:
Puede verificar si un objeto está en la clase 'NoneType':
Más información está disponible en Python Docs
fuente
Por prueba de valor de Verdad , 'Ninguno' prueba directamente como FALSO, por lo que la expresión más simple será suficiente:
fuente
True
para cualquier valor Falsy, no sóloNone
.