.. _listas: Listas ====== Una lista es una colección o un conjunto de elementos de datos que pueden ser de diferente tipo y ser procesados dentro de una secuencia. .. ######################################### Hay que tener en cuenta que una lista de elementos en otros lenguajes de programación como C, C++, Java entre otros, es imperativo que todos los elementos sean del mismo tipo de datos, Lo que quiere decir que las listas o arreglos son conjuntos de solo un tipo, o sea, o son todos números enteros o todos los elementos son textos, etc. En Python no, la generación de listas es promiscuo al tipo de dato, por lo que se pueden mezclar variados tipos de datos en el mismo conjunto. ######################################## El tipo de datos que representa a las listas se llama "list" y se puede comprobar del siguiente modo: .. code-block:: python numeros = [1, 2, 3, 4, 5, 6] print(type(numeros)) La salida la otorga type que devuelve el tipo de elemento del objeto consultado, en este caso el resultado a mostrar es: .. code-block:: text Crear Listas ------------ Para crear listas existen dos maneras: * Usar una lista literal con los elementos entre corchetes .. code-block:: python numeros_primos = [2 , 3 , 5 , 7 , 11] lista_variada = [ 'hola' + 'mundo' , 24 * 7 , True or False ] El ejemplo anterior declara la variable "lista_variada" cuyo objetivo es demostrar una particularidad propia de `Python`, las listas pueden estar compuesta por elementos con variados tipos de datos, lo que a diferencia de otros lenguajes de programación como C, Java, C++, esto no seria posible, pues en su declaración se explicita el tipo de dato que contendran cada elemento del conjunto construido. A pesar de la promiscuidad de los elementos de una lista en `Python` se recomienda siempre utilizar elementos de tipo similar a fin de disminuir la posibilidad de error. * Utilizar la función List sobre un elemento iterable, por ejemplo .. code-block:: python string = "Hola Mundo" lista_con_list = list (string) print(lista_con_list) El ejemplo anterior nos entregará como resultado: .. code-block:: text ['H', 'o', 'l', 'a', ' ', 'M', 'u', 'n', 'd', 'o'] En donde cada carácter de la variable string forma parte de esta lista. Esto incluye el espacio en blanco entre Hola y Mundo. Recorrer las listas ------------------- Una lista es un objeto iterable y esto significa que sus elementos se pueden recorrer usando cualquier estructura repetitiva. Un ejemplo utilizando el ciclo for .. literalinclude:: ../examples/listas/listas_for.py La salida esperada del ejemplo anterior anterior es: .. code-block:: text El elemento 0 de la lista es 6 El elemento 1 de la lista es 1 El elemento 2 de la lista es 7 El elemento 3 de la lista es 8 El elemento 4 de la lista es 9 El ciclo "for" itera en cada uno de los elementos de la lista accediendo directamente a la posición y por ende al valor del elemento del conjunto. Recorriendo la lista con un ciclo while sería del modo .. literalinclude:: ../examples/listas/listas_while.py Salida .. code-block:: text El elemento 0 de la lista es 6 El elemento 1 de la lista es 1 El elemento 2 de la lista es 7 El elemento 3 de la lista es 8 El elemento 4 de la lista es 9 La salida esperada es la misma en ambos casos pero difieren en la construcción de la sintaxis debido a la implementación de cada estructura. La condición "while" irá en rango al largo de elementos disponibles en la lista y una variable "contador" llevará el control de esos elementos sumando un 1 al valor de la variable en cada iteración. Para acceder al valor se realiza mediante la posición del elemento para ser impreso. Operaciones varias sobre listas ------------------------------- A continuación se presentan una serie de operaciones usuales de las listas Largo de una lista ^^^^^^^^^^^^^^^^^^ La función "len" recibe como parámetro un objeto de tipo lista y devolverá un número que corresponde al total de elementos de la lista o el denominado largo de la lista. Ejemplo .. code-block:: python colores = ["Azul" ,"Rojo", "Verde", "Amarillo"] print(len(colores)) Salida .. code-block:: text 4 Ejemplo .. code-block:: python lista = [True, True, False] print(len(lista)) La salida esperada es 3 .. code-block:: python lista = [] len(lista) La salida espera es cero que corresponde a una lista vacía. Agregar elementos ^^^^^^^^^^^^^^^^^ Para agregar elementos es posible realizarlo de distintos modos: * Agrega un elemento al final de la lista. Para este modo se utiliza el método "append". Este método es propios de las listas y recibe como parámetro el valor a agregar. Ejemplo .. code-block:: python colores = ["Azul" ,"Rojo", "Verde", "Amarillo"] colores.append("Negro") print(colores) Salida .. code-block:: text ["Azul", "Rojo", "Verde", "Amarillo", "Negro"] De este modo se agregó el "string" 'Negro' al final de la lista declarada como "colores". Otra forma de agregar un elemento a la lista es utilizando el método "insert". Este método permite insertar un elemento en un lugar determinado y cuando la inserción es exitosa los elementos que están por sobre el elemento a insertar se moverán en una posición hacia la derecha. Lo anterior es debido a que el método "insert" recibe dos parámetros; el primero que refiere a la posición en donde se insertará el elemento en la lista y el segundo el elemento como tal. Ejemplo .. code-block:: python colores = ["Azul" ,"Rojo", "Verde", "Amarillo"] colores.insert(2, "Negro") print(colores) Salida .. code-block:: text ["Azul" ,"Rojo", "Negro", "Verde", "Amarillo"] En este ejemplo se inserta en la posición dos (partiendo del cero) en la lista de "colores" el elemento 'Negro'. Como se ha explicado, los elementos que están por sobre la posición dos ('Verde' y 'Amarillo') de la lista original de "colores" se han movido un espacio hacia la derecha en su posición. Acceder a una posición ^^^^^^^^^^^^^^^^^^^^^^ Los elementos individuales que están dentro de una lista se pueden obtener usando un índice. Un índice es básicamente un número que corresponde al lugar o posición en donde se almacenan los datos dentro de la lista y debe estar entre corchetes "[]". Ejemplo .. code-block:: python colores = ["Azul" ,"Rojo", "Verde", "Amarillo"] print(colores[0]) print(colores[3]) Salida .. code-block:: text Azul Amarillo Entonces será "colores[i]" (leyendose 'colores sub i'), en donde "i" corresponde número de la posición partiendo del cero y devolverá el I-ésimo valor de la lista. Modificar un elemento de una posición ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Del mismo modo en que el acceder a un valor es posible también poder modificar el I-ésimo elemento. Ejemplo .. code-block:: python colores = ["Azul" ,"Rojo", "Verde", "Amarillo"] colores[1] = "Rosado" colores[3] = "Negro" print(colores) Salida .. code-block:: text ['Azul', 'Rosado', 'Verde', 'Negro'] Se ha logrado modificar las posiciones 1 y 3 de la lista, reemplazando los elementos 'Rojo' por 'Rosado' y 'Amarillo' por 'Negro'. Se debe tener cuidado con los índices y el largo de la lista, porque si es sobrepasado el largo ocurrirá un error en el programa (excepción). Ejemplo .. code-block:: python colores = ["Azul" ,"Rojo", "Verde", "Amarillo"] colores[10] = "Azul" print(colores) Salida .. code-block:: text Traceback (most recent call last): File "", line 1, in IndexError: list assignment index out of range Eliminar un elemento ^^^^^^^^^^^^^^^^^^^^ Para eliminar un elemento de la lista podemos utilizar el método "remove" y se encargará de eliminar el primer elemento que encuentre en la lista. El método "remove" recibe como parámetro el elemento a eliminar. Ejemplo .. code-block:: python numeros = [7 , 0 , 3 , 9 , 8 , 2 , 4 , 2 , 2] numeros.remove(2) print(numeros) Salida .. code-block:: text [7 , 0 , 3 , 9 , 8 , 4 , 2 , 2] Se observa que el primer elemento dos (2) encontrado se ubicaba en la posición 5 de la lista ha sido el único elemento removido y esto, a pesar que existan otros elementos con el mismo valor (2). Una segunda forma posible de eliminar elementos de una lista es a través de su índice utilizando el método "del", logrando que el I-ésimo elemento de la lista sea extraído. Ejemplo .. code-block:: python numero = [7, 0, 3, 9, 8, 2, 4] del numero[2] print(numero) Salida .. code-block:: text [7, 0, 9, 8, 2, 4] El ejemplo demuestra que se ha eliminado el elemento con valor tres (2) cuyo índice es dos. El método "pop" también es otra alternativa para eliminar elementos. Su forma es remover un elemento de la lista en la posición especificada. Si no se declara una posición, será el último elemento de la lista el eliminado. .. code-block:: python numero = [7, 0, 3, 9, 8, 2, 4] numero.pop(2) print(numero) numero.pop() print(numero) Salida .. code-block:: text [7, 0, 9, 8, 2, 4] [7, 0, 9, 8, 2] La explicación a lo realizado. La primera instancia al método "pop" es declarar eliminar al elemento en la posición dos (2) cuyo valor es 3. En la segunda llamada al método "pop" no hay parámetro entregado, por lo que este asume que es el último elemento es el que se desea eliminar siendo el valor cuatro (4) el que saldrá de la lista. Para limpiar completamente una lista basta con declarar la variable como una lista vacía. Ejemplo .. code-block:: python numeros = [] Otra forma de realizar pero menos eficiente es eliminar elementos con una iteración utilizando una estructura repetitiva. Ejemplo .. code-block:: python numeros = [7 , 0 , 3 , 9 , 8 , 2 , 4 , 2 , 2] while numeros: a.pop(-1) Listas en orden inverso ^^^^^^^^^^^^^^^^^^^^^^^ Aunque es algo que puede ser poco inusual se es posible obtener los elementos de manera inversa. Ejemplo .. code-block:: python colores = ["Azul" ,"Rojo", "Verde", "Amarillo"] print(colores[-4]) print(colores[-1]) Salida .. code-block:: text Azul Amarillo Esto es porque el valor -4 contando desde derecha a izquierda es Azul y el -1 es Amarillo. Hay que estimar que está forma no considera como valor inicial al cero. Contar elementos ^^^^^^^^^^^^^^^^ Para contar elementos en una lista es efectivo invocar al método "count" propio del objeto "list". Este método permite contar cuántas veces un elemento se encuentra en la lista. Ejemplo .. code-block:: python letras = list("paralelepipedo") print(letras.count("p")) Salida .. code-block:: text 3 Al invocar al método "count" pasando como parámetro el caracter 'p', dice que se desea saber cuántas veces la letra "p" se encuentra en la lista "letras". El método "count" recorrerá cada uno de los elementos y los comparará para que al final de su acción logre entregar el valor de las coincidencia. Para el caso de no encontrarse el elemento el valor a devolver es zero (0) Ejemplo .. code-block:: python letras = list("paralelepipedo") print(letras.count("z")) Salida .. code-block:: text 0 Concatenar listas ^^^^^^^^^^^^^^^^^ Una forma sencilla y práctica de concatenar dos listas es utilizando el operador "+". Ejemplo .. code-block:: python colores1 = ["Azul" ,"Rojo", "Verde", "Amarillo"] colores2 = ["Rosado", "Celeste", "Negro"] colores = colores1 + colores2 print(colores) Salida .. code-block:: text ['Azul', 'Rojo', 'Verde', 'Amarillo', 'Rosado', 'Celeste', 'Negro'] La concatenación se da en primer lugar para la lista de colores1 a la que se le agrega todos los elementos de la lista colores2. Es recomendable siempre realizar la concatenación de las listas en una nueva variable, tal como se mostró en el ejemplo. Una segunda forma de concatenar listas es usando el método "extend". Este método recibe por parámetro una la lista que se agregará a la lista con la que se le instancia el método. Ejemplo .. code-block:: python colores = ["Azul" ,"Rojo", "Verde", "Amarillo"] colores_2 = ["Rosado", "Celeste", "Negro"] colores.extend(colores_2) print(colores) Salida .. code-block:: text ['Azul', 'Rojo', 'Verde', 'Amarillo', 'Rosado', 'Celeste', 'Negro'] Este método puede traer un tipo de problema, porque al estar agregando elementos a la misma lista los elementos y el conjunto 'original' es perdido y como consecuencia no puede o es más costoso volver a un punto inicial. Es posible también concatenar en base a una multiplicación logrando duplicar los elementos de la lista. Para esto es necesario utilizando el operador "*" Ejemplo .. code-block:: python numeros = [3.14 , 6.28 , 9.42] numeros = numeros * 2 print(numeros) Salida .. code-block:: text [3.14 , 6.28 , 9.42 , 3.14 , 6.28 , 9.42] Particionamiento ^^^^^^^^^^^^^^^^ Se puede particionar una lista utilizando lo que se conoce 'rebanado'. Se trata de crear una nueva lista a partir del I-ésimo hasta justo antes del je-ésimo elemento de la lista. En un modo práctico se establecen corchetes al final del la declaración de la lista y en él los valores de inicio, termino y de modo opcional los saltos. Ejemplo .. code-block:: python numeros = [1, 2, 3, 4, 5] temp = numeros[2:4] print(temp) Salida .. code-block:: text [3, 4] Acá en una lista denominada "temp" es una lista creada a partir de la lista "numeros" que contempla los datos de las posiciones entre 2 y 4. En resumidas cuentas son el 3 y 4 los valores de la nueva lista "temp". Ejemplo .. code-block:: python numeros = [1 ,4 ,9 ,16 ,25 ,36 ,49 ,64 , 81 , 100] print(numeros[2:9:2]) Salida .. code-block:: text [9, 25, 49, 81] En este ejemplo se incluye el tercer parámetro que refiere a los saltos entre el rango definido para 'rebanar', entonces se ha decido imprimir una 'nueva lista' entre el rango de 2 y 9 saltando de dos en dos a partir del número de inicio indicado. Copiado de listas ^^^^^^^^^^^^^^^^^ El copiado de listas no parece ser una acción trivial pues tiende a confundirse con la asignación. Ejemplo .. code-block:: python a = [1, 2, 3, 4, 5] b = a print(a) print(b) .. code-block:: text [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] Para este caso se ha 'igualado' un valor de la lista 'a' a una variable 'b'. Efectivamente paso a ser una lista, pero ¿qué sucede con los valores de la lista 'a' cuando editamos un valor en la lista 'b'? Ejemplo .. code-block:: python a = [1, 2, 3, 4, 5] b = a b[0] = 10 print("Lista a", a) print("Lista b", b) Salida .. code-block:: text Lista a [10, 2, 3, 4, 5] Lista b [10, 2, 3, 4, 5] Según la sintaxis anterior, hemos generado dos lista para dos variables distintas, pero que en realidad ambas apuntan a los mismos valores, por lo que si se edita un valor en "a" esto impacta a "b". En específico, no se ha realizado una copia sino que una asignación de valores referidos a un espacio en memoria en particular. .. image:: ../img/asignacion-listas.png Es posible comprobar esto utilizando el método "id" para las variables. El método "id" devolverá un número que representa a la identidad del objeto creado en un espacio en memoria. Ejemplo .. code-block:: python a = [1, 2, 3, 4, 5] b = a print(id(a)) print(id(b)) Salida .. code-block:: text 41232 41232 En ambos casos devuelve la misma identidad. El objetivo del copiado es generar que las listas se vean reflejadas en distintas área de la memoria como dos objetos independientes. O sea, que para copiar una lista de `Python` significa crear un nuevo objeto de `Python` cuyo contenido sea idéntico. Así lo representa la siguiente imagen. .. image:: ../img/copiado-listas.png Para generar un copiado podemos utilizar distintas formas: * **Utilizar un ciclo y agregar elemento a elemento** Ejemplo .. literalinclude:: ../examples/listas/copia_for.py Salida .. code-block:: text La lista a [1, 2, 3, 4, 5] La lista b [1, 2, 3, 4, 5] id de a 195968 id de b 198528 Ambas lista poseen los mismos elementos pero son objetos distintos pudiéndose comprobar la diferencia que existe entre ambas por los valores retornados por el método "id". * **Copiado por Slicing** Esta es una forma más elegante y común de hacerlo en `Python` y se trata de poner "[:]" junto a la variable de tipo lista. Ejemplo .. literalinclude:: ../examples/listas/copia_slicing.py Salida .. code-block:: text 3529856 3532416 Lista a [20, 2, 3, 4, 5] Lista b [30, 2, 3, 4, 5] Ambos id son distintos representando a dos objetos independientes. * **Copiar utilizando el método list** Es otra forma elegante de copiar una lista es utilizando del método "list()". Este método creará un nuevo objeto con valores idénticos a partir de una lista ya creada. Ejemplo .. literalinclude:: ../examples/listas/copia_by_list.py Salida .. code-block:: text 2923264 1268800 Lista a [20, 2, 3, 4, 5] Lista b [30, 2, 3, 4, 5] * **Usando el método copy** En python3 se introdujo un método denominado "copy" que realiza exactamente lo que dice su traducción, copiar. Ejemplo .. literalinclude:: ../examples/listas/copia_with_copy.py Salida .. code-block:: text 5064576 5067136 Lista a [10, 2, 3, 4, 5] Lista b [1, 2, 3, 4, 5] * **Usando el método deepcopy de la clase copy** Ejemplo .. code-block:: python from copy import deepcopy a = [1, 2, 3, 4, 5] b = deepcopy(a) ¿Cuál es la diferencia entre los métodos copy y deepcopy? * "copy" es una replica superficial * "deepcopy" es una copia profunda La diferencia entre copia superficial y profunda solo es relevante para objetos compuestos (objetos que contienen otros objetos, como listas o instancias de clase), por lo que: * Una copia superficial construye un nuevo objeto compuesto y luego (en la medida de lo posible) inserta referencias en él a los objetos encontrados en el original. * Una copia profunda construye un nuevo objeto compuesto para que luego y de modo recursivo inserte copias de los objetos encontrados en el original. Benchmark de copiado ^^^^^^^^^^^^^^^^^^^^ El siguiente script muestra tiempos y distintas formas de copiado de listas. .. literalinclude:: ../examples/listas/tiempo-copiado.py Listas por comprensión ---------------------- Las listas por comprensión (list comprehensions en inglés) son: * Característica muy útil que fue incorporada al lenguaje Python `PEP 202`_. * Una forma muy sencilla de crear listas en Python a partir de secuencias * Suponen un modo más elegante y rápido de escribir código, y que además se logra ejecutar más rápidamente por estar implementadas directamente en lenguaje C. .. _`PEP 202`: https://www.python.org/dev/peps/pep-0202/ La diferenciación entre la creación de una lista de un 'modo tradicional' y una lista creada por compresión está plasmada en el siguiente script. Ejemplo .. literalinclude:: ../examples/listas/comprension.py Las listas por comprensión están compuestas por corchetes que incluyen una expresión seguida de una o varias cláusula de "for" y/o "if". Ejemplo .. literalinclude:: ../examples/listas/comprension2.py Salida .. code-block:: text ['Hola', 'Mundo', 'Mundial!'] El uso de listas por comprensión lugar de bucles (tradicional) es una buena forma de definir rápidamente las listas, y como todavía estamos hablando de programación funcional, vale la pena señalar que las listas creadas a través de este modo no pueden depender del estado del programa. Esto generalmente los hace más concisos y más fáciles de leer que las listas hechas sin la comprensión. Las listas por comprensión son muy prácticas para crear subconjuntos (nueva lista) de una lista ya definida. En el siguiente ejemplo tenemos una lista llamada "cosas" que tiene varios elementos de tipo "string". Se quiere realizar una nueva lista a partir de "cosas" pero que solo contemple los primeros cuatro caracteres de cada uno de los elementos. Ejemplo .. literalinclude:: ../examples/listas/comprension3.py Salida .. code-block:: text ['avio', 'cami', 'auto', 'telé', 'celu', 'comp', 'lapt'] Ahora la lista "cosas_04" que es una nueva lista que fue creada a partir de la lista "cosas" También es posible crear `diccionarios`_ a partir de listas por comprensión .. _diccionarios: diccionarios.html Para entender qué son las listas por comprensión se puede tomar cuenta lo siguiente * En matemáticas ¿Qué es un conjunto? La respuesta sería que un conjunto es simplemente una colección de elementos bien definidos, en donde los elementos pueden ser cualquier cosa: números, letras, nombres, figuras, etc. * ¿Cómo se pueden definir los conjunto? Por extensión o por comprensión. Se define un conjunto por **extensión** cuando cada elemento se enumera de manera explícita. Ejemplo .. code-block:: python cosas_extension = ["avion", "camion","auto", "teléfono", "celular", "computador", "laptop"] Por comprensión no se mencionan los elementos uno por uno sino que se indica una propiedad que todos éstos cumplen: Ejemplo cosas_comprension = { :math:`\chi` | :math:`\chi \in` "a algo que ha sido creado" } En donde :math:`\chi` es un elemento que pertenece al conjunto de "a algo que ha sido creado". Se puede decir que el conjunto "cosas_extension" (A) es igual al conjuntos "cosas_comprension" (B) debido a que ambos tienen exactamente los mismos elementos a pesar de que el conjunto A se definió por extensión y B se definió por comprensión. Si esto es llevado a Python esto sería del modo: .. literalinclude:: ../examples/listas/comprension4.py Las listas por comprensión en sintaxis (`Python`) consisten (ejemplo anterior) en colocar entre corchetes una expresión ("2**x") seguida de una cláusula "for". Dicha cláusula es muy similar en intención a un ciclo "for", en donde la variable "x" tomará los valores devueltos por la función "range(10)" (los enteros del 0 al 9). A partir de cada valor que toma "x" se calcula el resultado de la expresión "2**x" (elevado al cuadrado) y con eso se determinan los valores finales de la lista resultante. Ejemplo .. code-block:: python # numero entre el 1 y 100 múltiplos de 7 y 10 [n for n in range (1, 101) if n%7 == 0 or n%10 == 7] Matrices bidimensionales ------------------------ Las matrices son arreglos de "n" dimensiones en donde se almacenan elementos y que pueden ser accedidos al igual que las listas mediante índices. Probablemente el caso más conocido es la matriz bidimensional, con "n" filas y "m" columnas. Es básicamente lo que se entiende por una tabla. Tabla 2 filas x 3 columnas .. code-block:: text --- --- --- | 1 | 2 | 3 | --- --- --- | 4 | 5 | 6 | --- --- --- A diferencia de lenguajes como `C`, en `Python` no resulta intuitivo el proceso de creación de una matriz ya que las matrices no son una estructura propia de `Python` y simplemente una matriz es una lista de listas que nosotros interpretamos desde el punto de vista matemático. Ejemplo .. code-block:: python matrix = [[1, 2, 3], [4, 5, 6]] El ejemplo representa un objeto lista ("matrix") con dos elementos de tipo lista en su interior, en donde el primer elemento de tipo lista contiene los valores de 1, 2, 3, y el segundo 4, 5 y 6, lo que representa a una matriz de "2x3" en `Python`. Recorrer matrix ^^^^^^^^^^^^^^^ Para recorrer los elementos de una matriz bidimensional debemos hacer uso de ciclos considerando que estaremos recorriendo listas dentro de listas por lo que siempre se hace necesario recorrer ambos objetos. Primero se recorren las filas y luego las columnas. Ejemplo .. literalinclude:: ../examples/listas/matrix-recorre.py El ejemplo representa a una matriz de "3x3". Cada uno de los elementos de la matriz es un "string". A través de un ciclo se recorre los elementos de la variable "matrix", tal cual se realiza con una lista normal. En la ejecución el primer elemento encontrado es una lista, por lo que se itera nuevamente sobre ese elemento encontrado por medio de un segundo ciclo. Este segundo ciclo no itera sobre "matrix", sino que lo hace sobre este elemento encontrado siendo asociado a una nueva variable (fila) que es 'creada como índice'. Salida .. code-block:: text auto casa edificio camión avión helicóptero bicicleta patín hotel Ejercicios propuestos ---------------------