Pregunta ¿Cómo puedo verificar si una lista está vacía?


Por ejemplo, si pasó lo siguiente:

a = []

¿Cómo reviso para ver si a ¿esta vacio?


2718
2017-09-10 06:20


origen


Respuestas:


if not a:
  print("List is empty")

Usar la booleanidad implícita de la lista vacía es bastante pitónico.


3886
2017-09-10 06:28



La manera pitónica de hacerlo es desde el Guía de estilo PEP 8 (dónde  significa "recomendado" y No significa "no recomendado"):

Para secuencias, (cadenas, listas, tuplas), use el hecho de que las secuencias vacías son falsas.   

Sí: if not seq:
     if seq:

No:  if len(seq):
     if not len(seq):

862
2017-09-10 10:33



Lo prefiero explícitamente:

if len(li) == 0:
    print('the list is empty')

De esta forma, es 100% claro que li es una secuencia (lista) y queremos probar su tamaño. Mi problema con if not li: ... es que da la falsa impresión de que li es una variable booleana.


517
2017-09-05 00:30



Otras personas parecen estar generalizando la pregunta más allá de las simples listas, así que pensé que agregaría una advertencia para un tipo diferente de secuencia que mucha gente podría usar, especialmente dado que este es el primer hit de Google para "matriz vacía de prueba de Python". .

Otros métodos no funcionan para matrices numpy

Debe tener cuidado con las matrices numpy, porque otros métodos funcionan bien para lists u otros contenedores estándar fallan para matrices numpy. Explico por qué a continuación, pero en resumen, el metodo preferido es usar size.

La forma "pitonica" no funciona: Parte 1

La forma "pythonic" falla con las matrices numpy porque Numpy intenta lanzar la matriz a una matriz de bools, y if x intenta evaluar todos esos bools de una vez por algún tipo de valor de verdad agregado. Pero esto no tiene ningún sentido, así que obtienes un ValueError:

>>> x = numpy.array([0,1])
>>> if x: print("x")
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

La forma "pitonica" no funciona: Parte 2

Pero al menos el caso anterior te dice que falló. Si tiene una matriz numpy con exactamente un elemento, el if la declaración "funcionará", en el sentido de que no se obtiene un error. Sin embargo, si ese elemento pasa a ser 0 (o 0.0, o false, ...), el if declaración dará como resultado incorrectamente false:

>>> x = numpy.array([0,])
>>> if x: print("x")
... else: print("No x")
No x

Pero claramente x existe y no está vacío! Este resultado no es lo que querías.

Utilizando len puede dar resultados inesperados

Por ejemplo,

len( numpy.zeros((1,0)) )

devuelve 1, aunque la matriz tenga cero elementos.

La forma numpythonic

Como se explica en el preguntas frecuentes scipy, el método correcto en todos los casos en que sabes que tienes una matriz numpy es usar if x.size:

>>> x = numpy.array([0,1])
>>> if x.size: print("x")
x

>>> x = numpy.array([0,])
>>> if x.size: print("x")
... else: print("No x")
x

>>> x = numpy.zeros((1,0))
>>> if x.size: print("x")
... else: print("No x")
No x

Si no está seguro de si podría ser un list, una matriz numpy, u otra cosa, podría combinar este enfoque con la respuesta @dubiousjim da para asegurarse de que se usa la prueba correcta para cada tipo. No es muy "pitónico", pero resulta que Numpy rompió intencionalmente la pitonidad en al menos este sentido.

Si necesita hacer algo más que simplemente verificar si la entrada está vacía, y está usando otras características numpy como indexación o operaciones matemáticas, probablemente sea más eficiente (y ciertamente más común) forzar la entrada ser una matriz numpy. Hay algunas funciones agradables para hacer esto rápidamente, lo más importante numpy.asarray. Esto toma su entrada, no hace nada si ya es una matriz, o envuelve su entrada en una matriz si es una lista, tupla, etc., y opcionalmente la convierte a su elección dtype. Por lo tanto, es muy rápido siempre que sea posible, y garantiza que solo asuma que la entrada es una matriz numpy. Usualmente solo usamos el mismo nombre, ya que la conversión a una matriz no volverá a estar fuera de la actual alcance:

x = numpy.asarray(x, dtype=numpy.double)

Esto hará que el x.size Verifique el trabajo en todos los casos que veo en esta página.


208
2018-02-21 16:48



Una lista vacía se considera falsa en las pruebas de valor real (ver documentación de Python)

a = []
if a:
     print "not empty"

@Daren Thomas

EDITAR: Otro punto en contra de las pruebas   la lista vacía como False: ¿qué pasa?   ¿polimorfismo? No deberías depender de   una lista es una lista. Debería solo   charlar como un pato, ¿cómo vas?   para obtener tu patoCollection para quack   '' Falso '' cuando no tiene elementos?

Tu duckCollection debería implementar __nonzero__ o __len__ entonces el if a: funcionará sin problemas.


103
2017-09-10 06:31



La respuesta de Patrick (aceptada) es correcto: if not a: es la forma correcta de hacerlo. La respuesta de Harley Holcombe es correcto que esto esté en la guía de estilo PEP 8. Pero lo que ninguna de las respuestas explica es por qué es una buena idea seguir el modismo, incluso si usted personalmente considera que no es lo suficientemente explícito o confuso para los usuarios de Ruby o lo que sea.

El código de Python, y la comunidad de Python, tiene modismos muy fuertes. Seguir esos modismos hace que su código sea más fácil de leer para cualquier persona con experiencia en Python. Y cuando violas esos modismos, esa es una señal fuerte.

Eso es verdad if not a: no distingue las listas vacías de None, o 0 numéricos, o tuplas vacías, o tipos de colección vacíos creados por el usuario, o tipos vacíos creados por el usuario que no son del todo recolectados, o una matriz NumPy de un solo elemento que actúa como escalares con valores falsey, etc. Y a veces es importante estar explícito sobre eso. Y en ese caso, sabes qué usted quiere ser explícito, para que pueda probar exactamente eso. Por ejemplo, if not a and a is not None: significa "cualquier falsey excepto None", mientras if len(a) != 0: significa "solo secuencias vacías, y cualquier cosa que no sea una secuencia es un error aquí", y así sucesivamente. Además de probar exactamente lo que quiere probar, esto también le indica al lector que esta prueba es importante.

Pero cuando no tienes nada para ser explícito, nada más que if not a: está engañando al lector. Estás señalando algo tan importante cuando no es así. (También puede hacer que el código sea menos flexible, o más lento, o lo que sea, pero eso es menos importante.) Y si por costumbre engañar al lector así, entonces cuando hacer Necesito hacer una distinción, va a pasar desapercibido porque has estado "llorando lobo" por todo tu código.


81
2017-12-03 02:21



La mejor forma de verificar si una lista está vacía

Por ejemplo, si pasó lo siguiente:

a = []

¿Cómo verifico si a está vacío?

Respuesta corta:

Coloque la lista en un contexto booleano (por ejemplo, con un if o whiledeclaración). Se pondrá a prueba False si está vacío, y True de otra manera. Por ejemplo:

if not a:                           # do this!
    print('a is an empty list')

Apelar a la autoridad

PEP 8, la guía de estilo oficial de Python para el código de Python en la biblioteca estándar de Python, afirma:

Para secuencias, (cadenas, listas, tuplas), use el hecho de que las secuencias vacías son falsas.

Yes: if not seq:
     if seq:

No: if len(seq):
    if not len(seq):

Deberíamos esperar que el código de biblioteca estándar sea lo más eficiente y correcto posible. Pero ¿por qué es ese el caso, y por qué necesitamos esta guía?

Explicación

Frecuentemente veo códigos como este de programadores experimentados nuevos en Python:

if len(a) == 0:                     # Don't do this!
    print('a is an empty list')

Y los usuarios de lenguajes perezosos pueden tener la tentación de hacer esto:

if a == []:                         # Don't do this!
    print('a is an empty list')

Estos son correctos en sus respectivos otros idiomas. Y esto es incluso semánticamente correcto en Python.

Pero lo consideramos no Pythonic porque Python admite estas semánticas directamente en la interfaz del objeto de la lista a través de la coerción booleana.

Desde el documentos (y tenga en cuenta específicamente la inclusión de la lista vacía, [])

Por defecto, un objeto se considera verdadero a menos que su clase lo defina   ya sea una __bool__() método que devuelve False o una __len__() método   que devuelve cero, cuando se llama con el objeto. Aquí están la mayoría de los objetos incorporados considerados falsos:

  • constantes definidas como falsas: None y False.
  • cero de cualquier tipo numérico: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
  • secuencias y colecciones vacías: '', (), [], {}, set(), range(0)

Y la documentación del modelo de datos:

object.__bool__(self)

Llamado para implementar pruebas de valor verdad y la operación incorporada bool(); debería regresar False o True. Cuando este método no está definido,    __len__() se llama, si está definido, y el objeto se considera verdadero si su resultado es distinto de cero. Si una clase no define ni __len__()   ni __bool__(), todas sus instancias se consideran verdaderas.

y

object.__len__(self)

Llamado para implementar la función incorporada len(). Debe devolver la longitud del objeto, un entero> = 0. Además, un objeto que no define un __bool__() método y cuyo __len__() el método devuelve cero se considera falso en un contexto booleano.

Entonces en vez de esto:

if len(a) == 0:                     # Don't do this!
    print('a is an empty list')

o esto:

if a == []:                     # Don't do this!
    print('a is an empty list')

Hacer esto:

if not a:
    print('a is an empty list')

Hacer lo que Pythonic generalmente rinde en rendimiento:

¿Vale la pena? (Tenga en cuenta que menos tiempo para realizar una operación equivalente es mejor :)

>>> import timeit
>>> min(timeit.repeat(lambda: len([]) == 0, repeat=100))
0.13775854044661884
>>> min(timeit.repeat(lambda: [] == [], repeat=100))
0.0984637276455409
>>> min(timeit.repeat(lambda: not [], repeat=100))
0.07878462291455435

Para la escala, este es el costo de llamar a la función y construir y devolver una lista vacía, que puede restar de los costos de las comprobaciones de vacío utilizadas anteriormente:

>>> min(timeit.repeat(lambda: [], repeat=100))
0.07074015751817342

Vemos eso ya sea verificar la longitud con la función incorporada len comparado con 0  o verificar contra una lista vacía es mucho menos rendimiento que el uso de la sintaxis incorporada del lenguaje según lo documentado.

¿Por qué?

Para el len(a) == 0 comprobar:

Primero Python tiene que verificar los globales para ver si len está sombreado

Luego debe llamar a la función, cargar 0y hacer la comparación de igualdad en Python (en lugar de hacerlo con C):

>>> import dis
>>> dis.dis(lambda: len([]) == 0)
  1           0 LOAD_GLOBAL              0 (len)
              2 BUILD_LIST               0
              4 CALL_FUNCTION            1
              6 LOAD_CONST               1 (0)
              8 COMPARE_OP               2 (==)
             10 RETURN_VALUE

Y para el [] == []tiene que crear una lista innecesaria y luego, nuevamente, hacer la operación de comparación en la máquina virtual de Python (en lugar de C)

>>> dis.dis(lambda: [] == [])
  1           0 BUILD_LIST               0
              2 BUILD_LIST               0
              4 COMPARE_OP               2 (==)
              6 RETURN_VALUE

La forma "Pythonic" es una comprobación mucho más simple y rápida ya que la longitud de la lista se almacena en caché en el encabezado de la instancia del objeto:

>>> dis.dis(lambda: not [])
  1           0 BUILD_LIST               0
              2 UNARY_NOT
              4 RETURN_VALUE

Evidencia de la fuente C y la documentación

PyVarObject

Esta es una extensión de PyObject eso agrega el ob_size campo. Esto solo se usa para objetos que tienen alguna noción de longitud. Este tipo no aparece a menudo en Python / C API. Corresponde a los campos definidos por la expansión de la PyObject_VAR_HEAD macro.

Desde la fuente c en Incluir / listobject.h:

typedef struct {
    PyObject_VAR_HEAD
    /* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
    PyObject **ob_item;

    /* ob_item contains space for 'allocated' elements.  The number
     * currently in use is ob_size.
     * Invariants:
     *     0 <= ob_size <= allocated
     *     len(list) == ob_size

He disfrutado investigando esto y dedico mucho tiempo a comisar mis respuestas. Si crees que voy a dejar algo, por favor avísame en un comentario.


80
2017-08-20 03:50



He visto el siguiente como preferido:

if not a:
    print("The list is empty or null")

62
2017-09-10 06:28