Saltar al contenido principal
LibreTexts Español

2.3: Colecciones y Looping- Listas y para

  • Page ID
    55082
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    Una lista, como su nombre lo indica, es una lista de datos (enteros, flotantes, cadenas, booleanos, o incluso otras listas o tipos de datos más complicados). Las listas de Python son similares a matrices o vectores en otros lenguajes. Al igual que las letras en cadenas, los elementos de una lista se indexan a partir de 0 usando la sintaxis []. También podemos usar corchetes para crear una lista con algunos elementos de diferentes tipos, aunque en la práctica no lo haremos a menudo.

    II.3_1_py_23_list1

    Al igual que con las cadenas, podemos usar la notación [] para obtener una sublista “slice”, y podemos usar la función len () para obtener la longitud de una lista.

    II.3_2_PY_24_Sublista

    Sin embargo, a diferencia de las cadenas, las listas son mutables, lo que significa que podemos modificarlas después de haber sido creadas, por ejemplo, reemplazando un elemento por otro elemento. Como se mencionó anteriormente, ¡las listas pueden incluso contener otras listas!

    II.3_3_py_25_list_mutable

    Normalmente queremos que nuestro código cree una lista vacía, y luego agregarle elementos de datos un elemento a la vez. Se devuelve una lista vacía llamando a la función list () sin parámetros. Dada una variable que hace referencia a un objeto list, podemos anexar un elemento al final usando el método.append (), dando al método el elemento que queremos anexar como parámetro.

    II.3_4_py_26_list_append

    Esta sintaxis puede parecer un poco extraña en comparación con lo que hemos visto hasta ahora. Aquí new_list.append (“G”) le está diciendo al objeto list a la variable new_list que se refiere para ejecutar su método.append (), tomando como parámetro la cadena “G”. Exploraremos los conceptos de objetos y métodos de manera más formal en capítulos posteriores. Por ahora, consideremos la lista no sólo una recopilación de datos, sino un objeto “inteligente” con el que podemos interactuar usando. métodos.

    Tenga en cuenta que el método.append () pide a la lista que se modifique a sí misma (lo que puede hacer, porque las listas son mutables), pero esta operación no devuelve nada de uso. [1]

    imagen

    Este tipo de comando abre la posibilidad de algunos errores insidiosos; por ejemplo, una línea como new_list = new_list.append (“C”) parece bastante inocente y no causa ningún error inmediato, pero probablemente no sea lo que pretendía el programador. El motivo es que la llamada new_list.append (“C”) solicita satisfactoriamente a la lista que se modifique, pero luego se devuelve el valor None, que se asignaría a la variable new_list con la asignación. Al final de la línea, new_list se referirá a Ninguno, y la lista en sí ya no será accesible. (De hecho, será basura recolectada a su debido tiempo.) En resumen, use some_list.append (el), no some_list = some_list.append (el).

    A menudo queremos ordenar listas, lo que podemos hacer de dos maneras. Primero, podríamos usar la función sort (), que toma una lista como parámetro y devuelve una nueva copia de la lista en orden ordenado, dejando solo el original. Alternativamente, podríamos llamar a un método lists .sort () para pedirle a una lista que se ordene en su lugar.

    II.3_6_PY_28_list_clasificación

    Al igual que con el método .append () anterior, el método .sort () devuelve None, por lo que lo siguiente seguramente habría resultado en un error: a_list = a_list.sort ().

    En este punto, uno sería perdonado por pensar eso. siempre devuelven None y así la asignación basada en los resultados no es útil. Pero antes de pasar de las listas, introduzcamos una forma sencilla de dividir una cadena en una lista de subcadenas, usando el método .split () en un tipo de datos de cadena. Por ejemplo, dividamos una cadena donde quiera que ocurra la subsecuencia “TA”.

    II.3_7_py_29_string_split

    Si la secuencia fuera en cambio “CGCGTATACAGA”, la lista resultante habría contenido ["CGCG”, “”, “CAGA"] (es decir, uno de los elementos sería una cadena vacía de longitud cero). Este ejemplo ilustra que las cadenas, al igual que las listas, también son objetos “inteligentes” con los que podemos interactuar usando. métodos. (De hecho, también lo son los enteros, los flotadores y todos los demás tipos de Python que cubriremos).

    Tuplas (Listas inmutables)

    Como se señaló anteriormente, las listas son mutables, lo que significa que pueden ser alteradas después de su creación. En algunos casos especiales, es útil crear una versión inmutable de una lista, llamada “tupla” en Python. Al igual que las listas, las tuplas se pueden crear de dos maneras: con la función tupla () (que devuelve una tupla vacía) o directamente.

    II.3_8_PY_29_2_tupla

    Las tuplas funcionan como listas; podemos llamar len () en ellas y extraer elementos o rebanadas con sintaxis []. No podemos cambiar, eliminar o insertar elementos. [2]

    Bucle con para

    Un for-loop en Python ejecuta un bloque de código, una vez por cada elemento de un tipo de datos iterable: uno al que se puede acceder un elemento a la vez, en orden. Resulta que tanto cadenas como listas son tales tipos iterables en Python, aunque por ahora exploraremos solo iterar sobre listas con bucles for.

    Un bloque es un conjunto de líneas de código que se agrupan como una unidad; en muchos casos también se ejecutan como una unidad, quizás más de una vez. Los bloques en Python se indican al estar sangrados un nivel adicional (generalmente con cuatro espacios, recuerde que es consistente con esta práctica de sangría).

    Cuando se usa un for-loop para iterar sobre una lista, necesitamos especificar un nombre de variable que haga referencia a cada elemento de la lista a su vez.

    II.3_9_py_30_for_loop1

    En lo anterior, una línea tiene sangría y un nivel adicional justo debajo de la línea que define el bucle for. En el bucle for, la variable gene_id se establece para hacer referencia a cada elemento de la lista gene_ids a su vez. Aquí está la salida del bucle:

    II.3_10_py_30_2_for_loop1_out

    El uso de bucles for en Python a menudo confunde a los principiantes, porque se está asignando una variable (por ejemplo, gen_id) sin usar el operador de asignación standard =. Si ayuda, puedes pensar en el primer bucle a través del bloque como ejecutar gene_id = gene_ids [0], la próxima vez como ejecutar gene_id = gene_ids [1], y así sucesivamente, hasta que se hayan utilizado todos los elementos de gene_ids.

    Los bloques pueden contener varias líneas (incluidas las líneas en blanco) para que varias líneas de código puedan funcionar juntas. Aquí hay un bucle modificado que mantiene una variable de contador, incrementándola en una cada vez.

    II.3_11_py_30_3_for_loopcounter

    La salida de este bucle sería la misma que la salida anterior, con una línea adicional de impresión 3 (el contenido del contador después de que termine el bucle).

    Algunos errores comunes al usar estructuras de bloques en Python incluyen los siguientes, muchos de los cuales resultarán en un IndentationError.

    1. No usar el mismo número de espacios para cada nivel de sangría, o mezclar sangría de pestaña con sangría de múltiples espacios. (La mayoría de los programadores de Python prefieren usar cuatro espacios por nivel).
    2. Olvidar el colon: eso termina la línea antes del bloque.
    3. Usar algo así como una línea for-loop que requiere un bloque, pero no sangrar la siguiente línea.
    4. Innecesariamente sangría (creación de un bloque) sin una línea de definición de bucle correspondiente.

    A menudo queremos recorrer un rango de enteros. Convenientemente, la función range () devuelve una lista de números. [3] Comúnmente toma dos parámetros: (1) el entero inicial (inclusive) y (2) el entero final (exclusivo). Así podríamos programar nuestro for-loop de manera ligeramente diferente generando una lista de enteros para usar como índices, e iterando sobre eso:

    II.3_12_PY_31_por_Loop2

    La salida de uno de los bucles anteriores:

    II.3_13_py_31_2_for_loop2_out

    El segundo ejemplo anterior ilustra la justificación detrás de la naturaleza inclusivo/exclusiva de la función range (): debido a que los índices comienzan en cero y van a uno menos que la longitud de la lista, podemos usar range (0, len (ids)) (en lugar de necesitar modificar el índice final) para correctamente iterar sobre los índices de ids sin conocer primero la longitud de la lista. Los programadores experimentados generalmente encuentran esto intuitivo, pero aquellos que no están acostumbrados a contar desde cero pueden necesitar algo de práctica. Debes estudiar estos ejemplos de bucle cuidadosamente, y probarlos. Estos conceptos suelen ser más difíciles para los principiantes, pero son importantes de aprender.

    Los bucles y los bloques que controlan pueden anidarse, con un efecto poderoso:

    II.3_14_Nested_loop_Illustrated

    En lo anterior, el bucle for externo controla un bloque de cinco líneas; contenido dentro está el bucle for interno que controla un bloque de solo dos líneas. El bloque exterior se refiere principalmente a la variable i, mientras que el bloque interno se refiere principalmente a la variable j. Vemos que ambos bloques también hacen uso de variables definidas fuera de ellos; el bloque interno hace uso de sum, i, y j, mientras que las líneas específicas del bloque externo hacen uso de sum e i (pero no j). Este es un patrón común que veremos con más frecuencia. ¿Se puede determinar el valor del total al final sin ejecutar el código?

    Comprensiones de listas

    Python y algunos otros lenguajes incluyen sintaxis taquigráfica especializada para crear listas a partir de otras listas conocidas como comprensiones de listas. Efectivamente, esta taquigrafía combina una sintaxis for-loop y una sintaxis de creación de listas en una sola línea.

    Aquí hay un ejemplo rápido: comenzando con una lista de números [1, 2, 3, 4, 5, 6], generamos una lista de cuadrados ([1, 4, 9, 16, 25, 36]):

    II.3_15_py_33_2_list_comp_1

    Aquí estamos usando una convención de nomenclatura de num en nums, pero como un for-loop, la variable loop puede ser nombrada casi cualquier cosa; por ejemplo, squares = [x ** 2 for x in nums] lograría la misma tarea.

    Las comprensiones de listas pueden ser bastante flexibles y usarse de manera creativa. Dada una lista de secuencias, podemos generar fácilmente una lista de longitudes.

    II.3_16_py_33_3_list_comp_2

    Estas estructuras también admiten la “inclusión condicional”, aunque aún no hemos cubierto operadores como ==:

    II.3_17_py_33_4_list_comp_3

    El siguiente ejemplo genera una lista de 1 s por cada elemento donde la primera base es “T”, y luego usa la función sum () para resumir la lista, dando como resultado un recuento de secuencias que comienzan con “T”.

    II.3_18_py_33_5_list_comp_4

    Aunque muchos programadores de Python suelen usar comprensiones de listas, no las usaremos mucho en este libro. En parte, esto se debe a que son una característica que muchos lenguajes de programación no tienen, pero también porque pueden llegar a ser difíciles de leer y entender debido a su compacidad. Como ejemplo, ¿qué opinas que hace la siguiente comprensión? [x para x en rango (2, n) si x no en [j para i en rango (2, sqrtn) para j en rango (i*2, n, i)]] (Supongamos que n = 100 y sqrtn = 10. Este ejemplo también hace uso del hecho de que range () puede tomar un argumento step, como en range (start, stop, step).)

    Ejercicios

    1. ¿Cuál es el valor del total al final de cada bucle establecido a continuación? Primero, vea si puede calcular las respuestas a mano, y luego escribir y ejecutar el código con algunas declaraciones print () agregadas para verificar sus respuestas. II.3_19_py_33_sum_anidad_ex
    2. Supongamos que decimos que el primer bloque for-loop anterior tiene “profundidad” 1 y “ancho” 4, y el segundo tiene profundidad 2 y ancho 4, y el tercero tiene profundidad 3 y ancho 4. ¿Se puede definir una ecuación que indique cuál sería el total para un bloque de bucle anidado con profundidad d y ancho w? ¿Cómo se relaciona esta ecuación con el número de veces que tiene el intérprete para ejecutar la línea total = total + 1?
    3. Determinar una ecuación que relacione el valor final del total por debajo con el valor de x. II.3_20_py_34_sum_anidad_ex2
    4. Dada una declaración de una cadena de secuencia, como seq = “ATGATAGAGGGATACGGATAG”, y una subsecuencia de interés, como subseq = “GATA”, escribir algún código que imprima todas las ubicaciones de esa subcadena en la secuencia, una por línea, usando solo los conceptos de Python que hemos cubierto hasta ahora ( como len (), for-loops y .split ()). Para el ejemplo anterior, la salida debe ser 3, 11 y 18.

      Tu código aún debería funcionar si la subcadena ocurre al inicio o al final de la secuencia, o si la subsecuencia ocurre espalda con espalda (por ejemplo, en “GATACCGATATAGATA”, “GATA” ocurre en las posiciones 1, 7 y 11). Como indicio, puede asumir que la subsecuencia no se superpone (por ejemplo, no necesita preocuparse por ubicar “GAGA” en “GAGAGAGAGA”, lo que ocurriría en las posiciones 1, 3, 5 y 7).

    5. Supongamos que tenemos una matriz representada como una lista de columnas: cols = [[10, 20, 30, 40], [5, 6, 7, 8], [0.9, 0.10, 0.11, 0.12]]. Debido a que cada columna es una lista interna, se dice que esta disposición está en “orden de columna mayor”. Escribe algún código que produzca los mismos datos en “orden fila-mayor”; por ejemplo, las filas deben contener [[10, 5, 0.9], [20, 6, 0.10], [30, 7, 0.11], [40, 8, 0.12]]. Se puede suponer que todas las columnas tienen el mismo número de elementos y que la matriz es de al menos 2 por 2.

      Este problema es un poco complicado, pero te ayudará a organizar tus pensamientos alrededor de bucles y listas. Puede comenzar determinando primero el número de filas en los datos y luego construyendo la “estructura” de filas como una lista de listas vacías.


    1. Devuelve un tipo de datos especial conocido como Ninguno, que permite que exista una variable pero no haga referencia a ningún dato. (Técnicamente, Ninguno es un tipo de datos, aunque muy simple). Ninguno se puede usar como un tipo de marcador de posición, y así en algunas situaciones no es del todo inútil.
    2. Las tuplas son causa de una de las partes más confusas de Python, porque se crean encerrando una lista de elementos dentro de paréntesis, pero las llamadas a funciones también toman parámetros listados dentro de paréntesis, ¡y las expresiones matemáticas también se agrupan por paréntesis! Considera la expresión (4 + 3) * 2. ¿Es (4 + 3) un número entero o una tupla de un solo elemento? En realidad, es un entero. Por defecto, Python busca una coma para determinar si se debe crear una tupla, por lo que (4 + 3) es un entero, mientras que (4 + 3, 8) es una tupla de dos elementos y (4 + 3,) es una tupla de un solo elemento. Use paréntesis deliberadamente en Python: ya sea para agrupar expresiones matemáticas, crear tuplas o llamar a funciones, donde el nombre de la función y el paréntesis de apertura son vecinos, como en print (a) en lugar de print (a). Agregar innecesariamente paréntesis (y por lo tanto crear tuplas accidentalmente) ha sido la causa de algunos errores difíciles de encontrar.
    3. Una alternativa a range () en Python 2.7 es xrange (), que produce un tipo iterable que funciona como una lista de números pero que es más eficiente en la memoria. En versiones más recientes de Python (3.0 y superiores) la función range () funciona como xrange () y xrange () ha sido eliminada. Los programadores que usan Python 2.7 pueden desear usar xrange () para obtener eficiencia, pero nos quedaremos con range () para que nuestro código funcione con la más amplia variedad de versiones de Python, incluso si sacrifica la eficiencia en algunos casos. Hay una diferencia importante entre range () y xrange () en Python 2.7: range () devuelve una lista, mientras que xrange () devuelve un tipo iterable que carece de algunas características de listas verdaderas. Por ejemplo, nums = range (0, 4) seguido de nums [3] = 1000 daría como resultado nums referenciando [0, 1, 2, 1000], mientras que nums = xrange (0, 4) seguido de nums [3] = 1000 produciría un error.

    This page titled 2.3: Colecciones y Looping- Listas y para is shared under a CC BY-NC-SA license and was authored, remixed, and/or curated by Shawn T. O’Neil (OSU Press) .