1212 votos

objeto nulo en Python?

¿Cómo puedo referir al objeto null en Python?

1652voto

Ben James Puntos 41165

En Python, el objeto 'null' es el singleton None.

La mejor forma de comprobar las cosas por "Noneness" es el uso de la identidad del operador, is:

if foo is None:
    ...

182voto

mike Puntos 3565

None ¿Python es nulo?

No hay null en Python; en su lugar existe None . Como ya se ha dicho, la forma más precisa de comprobar que algo se ha dado None como valor es utilizar el is operador de identidad, que comprueba que dos variables se refieren al mismo objeto.

>>> foo is None
True
>>> foo = 'bar'
>>> foo is None
False

Lo básico

Sólo hay y puede haber una None

None es la única instancia de la clase NoneType y cualquier otro intento de instanciar esa clase devolverá el mismo objeto, lo que hace que None un singleton. Los recién llegados a Python a menudo ven mensajes de error que mencionan NoneType y se preguntan qué es. Es mi opinión personal que estos mensajes podrían simplemente mencionar None por su nombre porque, como veremos en breve, None deja poco espacio a la ambigüedad. Así que si ves algún TypeError mensaje que menciona que NoneType no puede hacer esto o no puede hacer aquello, simplemente sepa que es el None que estaba siendo utilizado de una manera que no puede.

También, None es una constante incorporada. Tan pronto como se inicia Python, está disponible para su uso desde cualquier lugar, ya sea en el módulo, clase o función. NoneType por el contrario no lo es, tendría que obtener primero una referencia a ella consultando None para su clase.

>>> NoneType
NameError: name 'NoneType' is not defined
>>> type(None)
NoneType

Puede comprobar None con la función de identidad de Python id() . Devuelve el número único asignado a un objeto, cada objeto tiene uno. Si el id de dos variables es el mismo, entonces apuntan de hecho al mismo objeto.

>>> NoneType = type(None)
>>> id(None)
10748000
>>> my_none = NoneType()
>>> id(my_none)
10748000
>>> another_none = NoneType()
>>> id(another_none)
10748000
>>> def function_that_does_nothing(): pass
>>> return_value = function_that_does_nothing()
>>> id(return_value)
10748000

None no se puede sobrescribir

En versiones mucho más antiguas de Python (antes de 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
>>> class SomeClass(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
>>> class SomeClass:
...     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 todos los None las referencias son las mismas. No hay ninguna "costumbre" None .

Para comprobar None utilizar el is operador

Cuando se escribe código, se puede tener la tentación de probar Noneness así:

if value==None:
    pass

O para comprobar la falsedad así

if not value:
    pass

Tienes que entender las implicaciones y por qué a menudo es una buena idea ser explícito.

Caso 1: comprobar si un valor es None

¿Por qué?

value is None

en lugar de

value==None

?

La primera equivale a:

id(value)==id(None)

Mientras que la expresión value==None se aplica de hecho así

value.__eq__(None)

Si el valor es realmente None entonces tendrás lo que esperabas.

>>> nothing = function_that_does_nothing()
>>> nothing.__eq__(None)
True

En la mayoría de los casos el resultado será el mismo, pero el __eq__() abre una puerta que anula cualquier garantía de exactitud, ya que puede ser anulado en una clase para proporcionar un comportamiento especial.

Considera esta clase.

>>> class Empty(object):
...     def __eq__(self, other):
...         return not other

Así que te lo pruebas None y funciona

>>> empty = Empty()
>>> empty==None
True

Pero entonces también funciona con la cadena vacía

>>> empty==''
True

Y sin embargo

>>> ''==None
False
>>> empty is None
False

Caso 2: Uso de None como un booleano

Las dos pruebas siguientes

if value:
    # Do something

if not value:
    # Do something

se evalúan de hecho como

if bool(value):
    # Do something

if not bool(value):
    # Do something

None es un "falso", lo que significa que si se convierte en un booleano devolverá False y si se aplica el not devolverá True . Sin embargo, tenga en cuenta que no es una propiedad exclusiva de None . Además de False la propiedad la comparten las listas vacías, las tuplas, los conjuntos, los dicts, las cadenas, así como 0, y todos los objetos de las clases que implementan la propiedad __bool__() método mágico para devolver False .

>>> bool(None)
False
>>> not None
True

>>> bool([])
False
>>> not []
True

>>> class MyFalsey(object):
...     def __bool__(self):
...         return False
>>> f = MyFalsey()
>>> bool(f)
False
>>> not f
True

Por lo tanto, al probar las variables de la siguiente manera, sea muy consciente de lo que está incluyendo o excluyendo de la prueba:

def some_function(value=None):
    if not value:
        value = init_value()

En lo anterior, ¿quieres llamar a init_value() cuando el valor se establece específicamente en None o quiere decir que un valor establecido en 0 ¿o la cadena vacía, o una lista vacía también debería activar la inicialización? Como dije, hay que tener cuidado. Como suele ocurrir, en Python lo explícito es mejor que lo implícito .

None en la práctica

None utilizado como valor de la señal

None tiene un estatus especial en Python. Es un valor base favorito porque muchos algoritmos lo tratan como un valor excepcional. En tales escenarios puede ser utilizado como una bandera para señalar que una condición requiere algún manejo especial (como el establecimiento de un valor por defecto).

Puede asignar None a los argumentos de la palabra clave de una función y luego probarlo explícitamente.

def my_function(value, param=None):
    if param is None:
        # Do something outrageous!

Puede devolverlo por defecto cuando intente llegar a un atributo de un objeto y luego probarlo explícitamente antes de hacer algo especial.

value = getattr(some_obj, 'some_attribute', None)
if value is None:
    # do something spectacular!

Por defecto, los diccionarios get() el método devuelve None al intentar acceder a una clave inexistente:

>>> some_dict = {}
>>> value = some_dict.get('foo')
>>> value is None
True

Si se intentara acceder a ella utilizando la notación de subíndice a KeyError se elevaría

>>> value = some_dict['foo']
KeyError: 'foo'

Del mismo modo, si intentas hacer estallar un elemento inexistente

>>> value = some_dict.pop('foo')
KeyError: 'foo'

que se puede suprimir con un valor por defecto que suele ser None

value = some_dict.pop('foo', None)
if value is None:
    # Booom!

None se utiliza como bandera y como valor válido

Los usos descritos de None se aplica cuando no se considera un valor válido, sino más bien una señal para hacer algo especial. Sin embargo, hay situaciones en las que a veces es importante saber dónde None porque aunque se utilice como señal también podría ser parte de los datos.

Cuando se consulta un objeto por su atributo con getattr(some_obj, 'attribute_name', None) volviendo None no te dice si el atributo al que intentabas acceder estaba configurado como None o si estuviera totalmente ausente del objeto. La misma situación se da cuando se accede a una clave de un diccionario, como some_dict.get('some_key') No sabes si some_dict['some_key'] o si sólo está configurado como None . Si necesita esa información, la forma habitual de hacerlo es intentar acceder directamente al atributo o a la clave desde un try/except construir:

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 here
    if value is None:
        # Do something here because the attribute was set to None
except AttributeError:
    # We're now handling 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)

Lo mismo ocurre con el dictado:

try:
    value = some_dict['some_key']
    if value is None:
        # Do something here because 'some_key' is set to None
except KeyError:
    # 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 los casos de objetos y diccionarios. ¿Y las funciones? Lo mismo, pero para ello utilizamos el argumento de la palabra clave doble asterisco:

def my_function(**kwargs):
    try:
        value = kwargs['some_key']
        if value is None:
            # Do something because 'some_key' is explicitly
            # set to None
    except KeyError:
        # We assign the default
        value = None
        # And since it's not coming from the caller.
        log_something('did not receive "some_key"')

None se utiliza sólo como un valor válido

Si encuentra que su código está plagado de lo anterior try/except patrón simplemente para diferenciar entre None banderas y None datos, entonces sólo hay que utilizar 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 utiliza para controlar y probar condiciones especiales (por ejemplo, límites, estado, etc.). Dicho valor se denomina centinela y se puede utilizar de la manera None se utiliza como señal. Es trivial crear un centinela en Python.

undefined = object()

El undefined es único y no hace casi nada que pueda ser de interés para un programa, por lo que es un excelente sustituto de None como bandera. 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 = None

    if param2 is undefined:
        # We got nothing here either
        log_something('param2 was missing')
        param2 = None

Con el dictado

value = some_dict.get('some_key', undefined)
if value is None:
    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 is None:
    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 he mencionado antes, los centinelas personalizados tienen algunas advertencias. En primer lugar, no son palabras clave como None , por lo que Python no los protege. Puedes sobrescribir tu undefined arriba en cualquier momento, en cualquier parte del módulo que se defina, así que ten cuidado con cómo los expones y utilizas. A continuación, la instancia devuelta por object() no es un singleton. Si se hace esa llamada 10 veces se obtienen 10 objetos diferentes. Por último, el uso de un centinela es altamente idiosincrásico. Un centinela es específico de la biblioteca en la que se utiliza y, como tal, su alcance debe limitarse generalmente a las partes internas de la biblioteca. No debería "filtrarse". El código externo sólo debería conocerlo si su propósito es extender o complementar la API de la biblioteca.

67voto

AndiDog Puntos 28417

No se llama null como en otros idiomas, sino None . Siempre hay una sola instancia de este objeto, por lo que se puede comprobar la equivalencia con x is None (comparación de identidades) en lugar de x == None Si lo desea.

28voto

Paolo Rovelli Puntos 892

En Python, para representar la ausencia de un valor, se puede utilizar el parámetro Ninguno valor ( types.NoneType.None ) para los objetos y "" (o len() == 0 ) para las cadenas. Por lo tanto:

if yourObject is None:  # if yourObject == None:
    ...

if yourString == "":  # if yourString.len() == 0:
    ...

En cuanto a la diferencia entre "==" y "is", la comprobación de la identidad del objeto mediante "==" debería ser suficiente. Sin embargo, dado que la operación "is" está definida como la operación de identidad del objeto, probablemente sea más correcto utilizarla, en lugar de "==". No estoy seguro de que haya siquiera una diferencia de velocidad.

De todos modos, puedes echar un vistazo:

0voto

s_mj Puntos 599

Utilice f cadena para conseguir que esto se resuelva.

year=None
year_val= 'null' if year is None else  str(year)
print(f'{year_val}')

null

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X