Python/Tipos de datos nativos/Presentación de las listas

De Wikilibros, la colección de libros de texto de contenido libre.

Índice de la sección
«Tipos de datos nativos»


Las listas son el caballo de tiro de Python. Si su única experiencia con listas son los array de Visual Basic o los datastore de Powerbuilder, prepárese para las listas de Python.

Nota: Una lista de Python es como un array en Perl. En Perl, las variables que almacenan arrays siempre empiezan con el carácter @; en Python, las variables se pueden llamar de cualquier manera, y Python se ocupa de saber el tipo que tienen.
Nota: Una lista en Python es mucho más que un array en Java (aunque puede usarse como uno si es realmente eso todo lo que quiere en esta vida). Una mejor analogía podría ser la clase ArrayList, que puede contener objetos arbitrarios y expandirse de forma dinámica según se añaden otros nuevos.

Definir listas[editar]

Ejemplo 3.6. Definición de una lista

>>> li = ["a", "b", "mpilgrim", "z", "ejemplo"]                         [1]
>>> li
['a', 'b', 'mpilgrim', 'z', 'ejemplo']
>>> li[0]                                                               [2]
'a'
>>> li[4]                                                               [3]
'ejemplo'
[1]Primero definimos una lista de cinco elementos. Observe que mantienen su orden original. Esto no es un accidente. Una lista es un conjunto ordenado de elementos encerrados entre corchetes.
[2] Una lista se puede usar igual que un array basado en cero. El primer elemento de cualquier lista que no esté vacía es siempre li[0].
[3] El último elemento de esta lista de cinco elementos es li[4], porque las listas siempre empiezan en cero.

Ejemplo 3.7. Indices negativos en las listas

>>> li
['a', 'b', 'mpilgrim', 'z', 'ejemplo']
>>> li[-1]                                                              [1]
'ejemplo'
>>> li[-3]                                                              [2]
'mpilgrim'
[1] Un índice negativo accede a los elementos desde el final de la lista contando hacia atrás. El último elemento de cualquier lista que no esté vacía es siempre li[-1].
[2] Si el índice negativo le confunde, piense de esta manera: li[-n] == li[len(li) - n]. De manera que en esta lista, li[-3] == li[5 - 3] == li[2].

Ejemplo 3.8. Slicing de una lista

>>> li
['a', 'b', 'mpilgrim', 'z', 'ejemplo']
>>> li[1:3]                                                             [1]
['b', 'mpilgrim']
>>> li[1:-1]                                                            [2]
['b', 'mpilgrim', 'z']
>>> li[0:3]                                                             [3]
['a', 'b', 'mpilgrim']
[1] Puede obtener un subconjunto de una lista, llamado "slice", especificando dos índices. El valor de retorno es una nueva lista que contiene todos los elementos de la primera lista, en orden, comenzando por el primer índice del slice (en este caso li[1]), hasta el segundo índice sin incluirlo (en este caso li[3]).
[2] El particionado (slicing) funciona si uno de los dos índices o ambos son negativos. Si le ayuda, puede pensarlo de esta manera: leyendo la lista de izquierda a derecha, el primer índice especifica el primer elemento que quiere, y el segundo especifica el primer elemento que no quiere. El valor de retorno es todo lo que hay en medio.
[3] Las listas empiezan en cero, así que li[0:3] devuelve los tres primeros elementos de la lista, empezando en li[0], y hasta li[3], pero sin incluirlo.

Ejemplo 3.9. Atajos para particionar

>>> li
['a', 'b', 'mpilgrim', 'z', 'ejemplo']
>>> li[:3]                                                              [1]
['a', 'b', 'mpilgrim']
>>> li[3:]                                                              [2]  [3]
['z', 'ejemplo']
>>> li[:]                                                               [4]
['a', 'b', 'mpilgrim', 'z', 'ejemplo']
[1] Si el índice izquierdo es 0, puede no ponerlo, y el 0 queda implícito. De manera que li[:3] es lo mismo que el li[0:3] del Ejemplo 3.8, "Slicing de una lista".
[2] De forma similar, si el índice de la derecha es la longitud de la lista, puede eliminarlo. Así que li[3:] es lo mismo que li[3:5], porque esta lista tiene cinco elementos.
[3] Advierta la simetría. En esta lista de cinco elementos, li[:3] devuelve los 3 primeros elementos, y li[3:] devuelve los dos últimos. En realidad, li[:n] siempre devolverá los primeros n elementos, y li[n:] devolverá el resto, independientemente del tamaño de la lista.
[4] Si se omiten ambos índices se incluyen todos los elementos de la lista. Pero no es la misma que la lista original li; es una nueva lista que tiene todos los mismos elementos. li[:] es un atajo para hacer una copia completa de una lista.

Añadir elementos a listas[editar]

Ejemplo 3.10. Adición de elementos a una lista

>>> li
['a', 'b', 'mpilgrim', 'z', 'ejemplo']
>>> li.append("nuevo")                                                  [1]
>>> li
['a', 'b', 'mpilgrim', 'z', 'ejemplo', 'nuevo']
>>> li.insert(2, "nuevo")                                               [2]
>>> li
['a', 'b', 'nuevo', 'mpilgrim', 'z', 'ejemplo', 'nuevo']
>>> li.extend(["dos", "elementos"])                                     [3]
>>> li
['a', 'b', 'nuevo', 'mpilgrim', 'z', 'ejemplo', 'nuevo', 'dos', 'elementos']
[1] append añade un único elemento al final de la lista.
[2] insert inserta un único elemento en una lista. El argumento numérico es el índice del primer elemento que cambia de posición. Observe que los elementos de la lista no tienen por qué ser únicos; ahora hay dos elementos con el valor 'nuevo', li[2] y li[6].
[3] extend concatena listas. Verá que no se llama a extend con varios argumentos; se le llama con uno, una lista. En este caso, esa lista tiene dos elementos.

Ejemplo 3.11. La diferencia entre extend y append

>>> li = ['a', 'b', 'c']
>>> li.extend(['d', 'e', 'f'])                                          [1]
>>> li
['a', 'b', 'c', 'd', 'e', 'f']
>>> len(li)                                                             [2]
6
>>> li[-1]
'f'
>>> li = ['a', 'b', 'c']
>>> li.append(['d', 'e', 'f'])                                          [3]
>>> li
['a', 'b', 'c', ['d', 'e', 'f']]
>>> len(li)                                                             [4]
4
>>> li[-1]
['d', 'e', 'f']
[1] Las listas tienen dos métodos, extend y append, que parecen hacer lo mismo, pero en realidad son completamente diferentes. extend toma un único argumento, que es siempre una lista, y añade cada uno de los elementos de esa lista a la original.
[2] Aquí empezamos con una lista de tres elementos ('a', 'b', y 'c'), y la extendemos con una lista de otros tres elementos ('d', 'e', y 'f'), de manera que ahora tenemos una de seis.
[3] Por otro lado, append toma un argumento, que puede ser cualquier tipo de dato, y simplemente lo añade al final de la lista. Aquí, estamos llamado al método append con un único argumento, que es una lista de tres elementos.
[4] Ahora la lista original, que empezó siendo una lista de tres elementos, contiene cuatro. ¿Por qué cuatro? Porque el último elemento que acabamos de añadir es una lista. Las listas contienen cualquier tipo de dato, incluyendo otras listas. Puede que esto es lo que usted quiere, puede que no. No use append si lo que quiere hacer es extend.

Buscar en listas[editar]

Ejemplo 3.12. Búsqueda en una lista

>>> li
['a', 'b', 'nuevo', 'mpilgrim', 'z', 'ejemplo', 'nuevo', 'dos', 'elementos']
>>> li.index("ejemplo")                                                     [1]
5
>>> li.index("nuevo")                                                       [2]
2
>>> li.index("c")                                                           [3]
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
ValueError: list.index(x): x not in list
>>> "c" in li                                                               [4]
False
[1] index encuentra la primera aparición de un valor en la lista y devuelve su índice.
[2] index encuentra la primera aparición de un valor en la lista. En este caso, 'nuevo' aparece dos veces en la lista, en li[2] y li[6], pero index devolverá sólo el primer índice, 2.
[3] Si el valor no se encuentra en la lista, Python lanza una excepción. Esto es notablemente diferente a la mayoría de los lenguajes, que devolverán algún índice inválido. Aunque pueda parecer irritante, es bueno, porque significa que el programa terminará con error al hallar la fuente del problema, en lugar de más adelante cuando intente usar el índice no válido.
[4] Para probar si un valor está en la lista, utilice in, que devuelve True si el valor existe o False si no.


Nota: Antes de la versión 2.2.1, Python no tenía un tipo booleano. Para compensarlo, Python aceptaba casi cualquier cosa en un contexto booleano (como una sentencia if), de acuerdo a las siguientes reglas:
  • 0 es falso; el resto de los números son verdaderos.
  • Una cadena vacía ("") es falso, cualquier otra cadena es verdadera.
  • Una lista vacía ([]) es falso; el resto de las listas son verdaderas.
  • Una tupla vacía (()) es falso; el resto de las tuplas son verdaderas.
  • Un diccionario vacío ({}) es falso; todos los otros diccionarios son verdaderos.
Estas reglas siguen aplicándose en Python 2.2.1 y siguientes, pero ahora además puedes usar un verdadero booleano, que tiene el valor de True o False. Tenga en cuenta las mayúsculas; estos valores, como todo lo demás en Python, las distinguen.

Borrar elementos de listas[editar]

Ejemplo 3.13. Borrado de elementos de una lista

>>> li
['a', 'b', 'nuevo', 'mpilgrim', 'z', 'ejemplo', 'nuevo', 'dos', 'elementos']
>>> li.remove("z")                                                          [1]
>>> li
['a', 'b', 'nuevo', 'mpilgrim', 'ejemplo', 'nuevo', 'dos', 'elementos']
>>> li.remove("nuevo")                                                      [2]
>>> li
['a', 'b', 'mpilgrim', 'ejemplo', 'nuevo', 'dos', 'elementos']
>>> li.remove("c")                                                          [3]
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
ValueError: list.remove(x): x not in list
>>> li.pop()                                                                [4]
'elementos'
>>> li
['a', 'b', 'mpilgrim', 'ejemplo', 'nuevo', 'dos']
[1] remove elimina la primera aparición de un valor en una lista.
[2] remove elimina sólo la primera aparición de un valor. En este caso, 'nuevo' aparecía dos veces en la lista, pero li.remove("nuevo") sólo eliminó la primera aparición.
[3] Si el valor no se encuentra en la lista, Python lanza una excepción. Esto semeja el comportamiento del método index.
[4] pop es una bestia interesante. Hace dos cosas: elimina el último elemento de la lista, y devuelve el valor que borró. Observará que esto es diferente de li[-1], que devuelve un valor pero no cambia la lista, y de li.remove(valor), que cambia la lista pero no devuelve un valor.

Uso de operadores de lista[editar]

Ejemplo 3.14. Operadores de lista

>>> li = ['a', 'b', 'mpilgrim']
>>> li = li + ['ejemplo', 'nuevo']                                      [1]
>>> li
['a', 'b', 'mpilgrim', 'ejemplo', 'nuevo']
>>> li += ['dos']                                                       [2]
>>> li
['a', 'b', 'mpilgrim', 'ejemplo', 'nuevo', 'dos']
>>> li = [1, 2] * 3                                                     [3]
>>> li
[1, 2, 1, 2, 1, 2]
[1] Las listas también se pueden concatenar con el operador +. lista = lista + otralista da el mismo resultado que lista.extend(otralista). Pero el operador + devuelve una nueva lista (concatenada) como valor, mientras que extend sólo altera una existente. Esto significa que extend es más rápido, especialmente para listas grandes.
[2] Python admite el operador +=. li += ['dos'] es equivalente a li.extend(['dos']). El operador += funciona con listas, cadenas y enteros, y también puede sobrecargarse para trabajar con clases definidas por el usuario (más sobre clases en el Capítulo 5.)
[3] El operador * funciona en las listas como repetidor. li = [1, 2] * 3 es el equivalente a li = [1, 2] + [1, 2] + [1, 2], que concatena las tres listas en una.

Atajos de creación de listas[editar]

Puede inicializar una lista a un tamaño, con un valor inicial para cada elemento:

>>> ceros = [0] * 5
>>> print(ceros)
[0, 0, 0, 0, 0]

Esto funciona para cualquier tipo de datos:

>>> foos = ['foo'] * 3
>>> print(foos)
['foo', 'foo', 'foo']

Pero hay una advertencia. Al construir una nueva lista multiplicando, Python copia cada elemento por referencia. Esto plantea un problema para los elementos mutables, por ejemplo, en una matriz multidimensional donde cada elemento es en sí mismo una lista. Adivinaría que la forma más fácil de generar una matriz bidimensional sería:

listadelistas = [[0] * 4] * 5

y esto funciona, pero probablemente no haga lo que esperas:

>>> listadelistas = [[0] * 4] * 5
>>> print(listadelistas)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0] ]
>>> listadelistas[0][2] = 1
>>> print(listadelistas)
[[0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0] ]

Lo que está sucediendo aquí es que Python está usando la misma referencia a la lista interna que los elementos de la lista externa. Otra forma de ver este problema es examinar cómo Python ve la definición anterior:

>>> listainterna = [0] * 4
>>> listadelistas = [listainterna] * 5
>>> print(listadelistas)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0] ]
>>> listainterna[2] = 1
>>> print(listadelistas)
[[0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0] ]

Suponiendo que el efecto anterior no es lo que pretende, una forma de solucionar este problema es usar listas por comprensión:

>>> listadelistas = [[0] * 4 for in range(5)]
>>> print(listadelistas)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0] ]
>>> listadelistas[0][2] = 1
>>> print(listadelistas)
[[0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0] ]

Comprensión de listas[editar]

Utilizando la comprensión de listas, describe el proceso mediante el cual se debe crear la lista. Para hacer eso, la lista se divide en dos partes. La primera es una imagen de cómo se verá cada elemento, y la segunda es lo que haces para conseguirlo.

Por ejemplo, digamos que tenemos una lista de palabras:

listOfWords = ["esto", "es", "una", "lista", "de", "palabras"]

Tomar la primera letra de cada palabra y hacer una lista usando la lista de comprensión, podemos hacer esto:

>>> listOfWords = ["esto", "es", "una", "lista", "de", "palabras"]
>>> elementos = [palabra[0] for palabra in listOfWords]
>>> print(elementos)
['t', 'i', 'a', 'l', 'o', 'w']

La comprensión de listas admite más de una declaración. Evaluará los elementos en todos los objetos secuencialmente y bucle sobre los objetos más cortos si un objeto es más largo que el resto.

>>> elemento = [x + y para x en 'gato' para y en 'bote']
>>> print(elemento)
['cp', 'co', 'ct', 'ap', 'ao', 'at', 'tp', 'to', 'tt']

La comprensión de la lista admite una declaración if, para incluir solo a los miembros en la lista que cumplan una determinada condición:

>>> print([x + y para x en 'gato' para y en 'olla'])
['cp', 'co', 'ct', 'ap', 'ao', 'at', 'tp', 'to', 'tt']
>>> print([x + y para x en 'gato' para y en 'olla' si x! = 't' y y! = 'o'])
['cp', 'ct', 'ap', 'at']
>>> print([x + y para x en 'gato' para y en 'bote' si x! = 't' o y! = 'o'])
['cp', 'co', 'ct', 'ap', 'ao', 'at', 'tp', 'tt']

En la versión 2.x, la comprensión de la lista de Python no define un alcance. Todas las variables que están vinculadas en una evaluación permanecen vinculadas a lo que estaban vinculadas por última vez cuando se completó la evaluación. En la versión 3.x, la comprensión de la lista de Python usa variables locales:

>>> print x, y #Entrada a python versión 2
t t # Salida usando Python 2

>>> print(x, y) #Entrada a la versión 3 de Python
NameError: el nombre 'x' no está definido # Python 3 devuelve un error porque no se filtraron xey

Esto es exactamente lo mismo que si la comprensión se había expandido a un grupo anidado explícitamente de una o más declaraciones 'for' y 0 o más declaraciones 'if'.

Lecturas complementarias sobre listas[editar]


Python: Índice · Introducción · Enlaces

Instalación de Python · Generalidades · Funciones, constantes nativas · Tipos de datos nativos · Herramientas de control de flujo · Definición de funciones · Leer y escribir archivos · Su primer programa en Python · Entrada y salida · Estructuras de datos · Errores y excepciones

Interfaces gráficas · Módulos relacionados con el sonido · Módulos relacionados con el tiempo · Módulos relacionados con la matemática