Diferències
Ací es mostren les diferències entre la revisió seleccionada i la versió actual de la pàgina.
Ambdós costats versió prèvia Revisió prèvia Següent revisió | Revisió prèvia | ||
info:cursos:netacad:python:pe1m3 [09/06/2022 12:31] – [listas] mate | info:cursos:netacad:python:pe1m3 [14/06/2022 11:07] (actual) – [Listas dentro de listas] mate | ||
---|---|---|---|
Línia 148: | Línia 148: | ||
time.sleep(1) | time.sleep(1) | ||
print(" | print(" | ||
+ | </ | ||
+ | <code python> | ||
+ | import time | ||
+ | |||
+ | for i in range(1,6): | ||
+ | time.sleep(1) | ||
+ | print(str(i)," | ||
</ | </ | ||
== break y continue | == break y continue | ||
Línia 594: | Línia 601: | ||
print(" | print(" | ||
== ordenamiento burbuja | == ordenamiento burbuja | ||
+ | ¿Cuántos pases necesitamos para ordenar la lista completa? | ||
+ | |||
+ | Resolvamos este problema de la siguiente manera: introducimos otra variable, su tarea es observar si se ha realizado algún intercambio durante el pase o no. Si no hay intercambio, | ||
+ | |||
+ | <code python> | ||
+ | |||
+ | for i in range(len(my_list) - 1): # necesitamos (5 - 1) comparaciones | ||
+ | if my_list[i] > my_list[i + 1]: # compara elementos adyacentes | ||
+ | my_list[i], my_list[i + 1] = my_list[i + 1], my_list[i] | ||
+ | </ | ||
+ | |||
+ | Deberías poder leer y comprender este programa sin ningún problema: | ||
+ | <code python> | ||
+ | swapped = True # Lo necesitamos verdadero (True) para ingresar al bucle while. | ||
+ | |||
+ | while swapped: | ||
+ | swapped = False # no hay intercambios hasta ahora | ||
+ | for i in range(len(my_list) - 1): | ||
+ | if my_list[i] > my_list[i + 1]: | ||
+ | swapped = True # ¡ocurrió el intercambio! | ||
+ | my_list[i], my_list[i + 1] = my_list[i + 1], my_list[i] | ||
+ | |||
+ | print(my_list) | ||
+ | </ | ||
+ | |||
+ | === El ordenamiento burbuja - versión interactiva | ||
+ | En el editor, puedes ver un programa completo, enriquecido por una conversación con el usuario, y que permite ingresar e imprimir elementos de la lista: El ordenamiento burbuja: versión final interactiva. | ||
+ | |||
+ | <code python> | ||
+ | my_list = [] | ||
+ | swapped = True | ||
+ | num = int(input(" | ||
+ | |||
+ | for i in range(num): | ||
+ | val = float(input(" | ||
+ | my_list.append(val) | ||
+ | |||
+ | while swapped: | ||
+ | swapped = False | ||
+ | for i in range(len(my_list) - 1): | ||
+ | if my_list[i] > my_list[i + 1]: | ||
+ | swapped = True | ||
+ | my_list[i], my_list[i + 1] = my_list[i + 1], my_list[i] | ||
+ | |||
+ | print(" | ||
+ | print(my_list) | ||
+ | </ | ||
+ | |||
+ | Python, sin embargo, tiene sus propios mecanismos de clasificación. Nadie necesita escribir sus propias clases, ya que hay un número suficiente de herramientas listas para usar. | ||
+ | |||
+ | Te explicamos este sistema de clasificación porque es importante aprender como procesar los contenidos de una lista y mostrarte como puede funcionar la clasificación real. | ||
+ | |||
+ | Si quieres que Python ordene tu lista, puedes hacerlo de la siguiente manera: | ||
+ | <code python> | ||
+ | my_list = [8, 10, 6, 2, 4] | ||
+ | my_list.sort() | ||
+ | print(my_list) | ||
+ | </ | ||
+ | |||
+ | Como puedes ver, todas las listas tienen un método denominado sort(), que las ordena lo más rápido posible. | ||
+ | |||
+ | == La vida al interior de las listas | ||
+ | Ahora queremos mostrarte una característica importante y muy sorprendente de las listas, que las distingue de las variables ordinarias. | ||
+ | |||
+ | Queremos que lo memorices, ya que puede afectar tus programas futuros y causar graves problemas si se olvida o se pasa por alto. | ||
+ | |||
+ | Echa un vistazo al fragmento en el editor. | ||
+ | |||
+ | El programa: | ||
+ | |||
+ | Crea una lista de un elemento llamada list_1. | ||
+ | La asigna a una nueva lista llamada list_2. | ||
+ | Cambia el único elemento de list_1. | ||
+ | Imprime la list_2. | ||
+ | La parte sorprendente es el hecho de que el programa mostrará como resultado: [2], no [1], que parece ser la solución obvia. | ||
+ | |||
+ | |||
+ | Las listas (y muchas otras entidades complejas de Python) se almacenan de diferentes maneras que las variables ordinarias (escalares). | ||
+ | |||
+ | Se podría decir que: | ||
+ | |||
+ | El nombre de una variable ordinaria es el nombre de su contenido. | ||
+ | El nombre de una lista es el nombre de una ubicación de memoria donde se almacena la lista. | ||
+ | Lee estas dos líneas una vez más, la diferencia es esencial para comprender de que vamos a hablar a continuación. | ||
+ | |||
+ | La asignación: | ||
+ | |||
+ | === Rebanadas Poderosas | ||
+ | Afortunadamente, | ||
+ | |||
+ | Una rebanada es un elemento de la sintaxis de Python que permite **hacer una copia nueva de una lista, o partes de una lista.** | ||
+ | |||
+ | En realidad, copia el contenido de la lista, no el nombre de la lista. | ||
+ | |||
+ | Esto es exactamente lo que necesitas. Echa un vistazo al fragmento de código a continuación: | ||
+ | |||
+ | <code python> | ||
+ | list_1 = [1] | ||
+ | list_2 = list_1[:] | ||
+ | list_1[0] = 2 | ||
+ | print(list_2) | ||
+ | </ | ||
+ | |||
+ | Su salida es **[1]**. | ||
+ | |||
+ | Esta parte no visible del código descrito como [:] puede producir una lista completamente nueva. | ||
+ | |||
+ | Una de las formas más generales de la rebanada es la siguiente: | ||
+ | |||
+ | <code python> | ||
+ | |||
+ | Como puedes ver, se asemeja a la indexación, | ||
+ | |||
+ | Una rebanada de este tipo **crea una nueva lista (de destino), tomando elementos de la lista de origen: los elementos de los índices desde el principio hasta el fin - 1.** | ||
+ | |||
+ | Nota: no hasta el fin, sino hasta fin-1. Un elemento con un índice igual a fin es el primer elemento el cual no participa en la segmentación. | ||
+ | |||
+ | Es posible utilizar valores negativos tanto para el inicio como para el fin(al igual que en la indexación). | ||
+ | |||
+ | Echa un vistazo al fragmento: | ||
+ | |||
+ | <code python> | ||
+ | my_list = [10, 8, 6, 4, 2] | ||
+ | new_list = my_list[1: | ||
+ | print(new_list) | ||
+ | </ | ||
+ | |||
+ | La lista new_list contendrá fin - inicio (3 - 1 = 2) elementos â los que tienen índices iguales a 1 y 2 (pero no 3). | ||
+ | |||
+ | La salida del fragmento es: **[8, 6]** | ||
+ | |||
+ | === Rebanadas - índices negativos | ||
+ | Observa el fragmento de código a continuación: | ||
+ | <code python> | ||
+ | my_list[start: | ||
+ | </ | ||
+ | |||
+ | Para confirmar: | ||
+ | |||
+ | **start** es el índice del primer elemento **incluido en la rebanada.** | ||
+ | **end** es el índice del primer elemento **no incluido en la rebanada.** | ||
+ | |||
+ | Así es como los índices negativos funcionan en las rebanadas: | ||
+ | <code python> | ||
+ | my_list = [10, 8, 6, 4, 2] | ||
+ | new_list = my_list[1: | ||
+ | print(new_list) | ||
+ | </ | ||
+ | |||
+ | El resultado del fragmento es: | ||
+ | <code python> | ||
+ | [8, 6, 4] | ||
+ | salida | ||
+ | </ | ||
+ | |||
+ | Si start especifica un elemento que se encuentra más allá del descrito por end (desde el punto de vista inicial de la lista), la rebanada estará vacía: | ||
+ | <code python> | ||
+ | my_list = [10, 8, 6, 4, 2] | ||
+ | new_list = my_list[-1: | ||
+ | print(new_list) | ||
+ | </ | ||
+ | |||
+ | La salida del fragmento es: | ||
+ | <code python> | ||
+ | [] | ||
+ | </ | ||
+ | |||
+ | === Rebanadas: continuación | ||
+ | Si omites el start en tu rebanada, se supone que deseas obtener un segmento que comienza en el elemento con índice 0. | ||
+ | <code python> | ||
+ | <code python> | ||
+ | new_list = my_list[:3] | ||
+ | print(new_list)</ | ||
+ | <code python> | ||
+ | |||
+ | Del mismo modo, si omites el end en tu rebanada, se supone que deseas que el segmento termine en el elemento con el índice len(my_list). | ||
+ | <code python> | ||
+ | my_list[start: | ||
+ | </ | ||
+ | <code python> | ||
+ | new_list = my_list[3:] | ||
+ | print(new_list)</ | ||
+ | <code python> | ||
+ | |||
+ | Como hemos dicho anteriormente, | ||
+ | |||
+ | La instrucción **del** descrita anteriormente puede **eliminar más de un elemento de la lista a la vez, también puede eliminar rebanadas**: | ||
+ | |||
+ | <code python> | ||
+ | del my_list[1: | ||
+ | print(my_list)</ | ||
+ | Nota: En este caso, la rebanada **¡no produce ninguna lista nueva!** | ||
+ | |||
+ | Al eliminar la rebanada del código, su significado cambia dramáticamente. | ||
+ | <code python> | ||
+ | del my_list | ||
+ | print(my_list)</ | ||
+ | La instrucción del **eliminará la lista, no su contenido**. | ||
+ | |||
+ | === Los operadores in y not in | ||
+ | Python ofrece dos operadores muy poderosos, capaces de revisar la lista para verificar si un valor específico está almacenado dentro de la lista o no. | ||
+ | |||
+ | Estos operadores son: | ||
+ | <code python> | ||
+ | elem in my_list | ||
+ | elem not in my_list | ||
+ | </ | ||
+ | |||
+ | El primero de ellos (in) verifica si un elemento dado (el argumento izquierdo) está actualmente almacenado en algún lugar dentro de la lista (el argumento derecho) - el operador devuelve True en este caso. | ||
+ | |||
+ | El segundo (not in) comprueba si un elemento dado (el argumento izquierdo) está ausente en una lista - el operador devuelve True en este caso. | ||
+ | |||
+ | === Listas dentro de listas | ||
+ | Las listas pueden constar de escalares (es decir, números) y elementos de una estructura mucho más compleja (ya has visto ejemplos como cadenas, booleanos o incluso otras listas en las lecciones del Resumen de la Sección anterior). Veamos más de cerca el caso en el que los elementos de una lista son listas. | ||
+ | |||
+ | A menudo encontramos estos arreglos en nuestras vidas. Probablemente el mejor ejemplo de esto sea un tablero de ajedrez. | ||
+ | |||
+ | Un tablero de ajedrez está compuesto de filas y columnas. Hay ocho filas y ocho columnas. Cada columna está marcada con las letras de la A a la H. Cada línea está marcada con un número del uno al ocho. | ||
+ | |||
+ | La ubicación de cada campo se identifica por pares de letras y dígitos. Por lo tanto, sabemos que la esquina inferior derecha del tablero (la que tiene la torre blanca) es A1, mientras que la esquina opuesta es H8. | ||
+ | |||
+ | |||
+ | Supongamos que podemos usar los números seleccionados para representar cualquier pieza de ajedrez. También podemos asumir que cada fila en el tablero de ajedrez es una lista. | ||
+ | |||
+ | Observa el siguiente código: | ||
+ | <code python> | ||
+ | row = [] | ||
+ | |||
+ | for i in range(8): | ||
+ | row.append(WHITE_PAWN) | ||
+ | </ | ||
+ | |||
+ | Crea una lista que contiene ocho elementos que representan la segunda fila del tablero de ajedrez: la que está llena de peones (supon que WHITE_PAWN es un símbolo predefinido que representa un peón blanco). | ||
+ | |||
+ | El mismo efecto se puede lograr mediante una comprensión de lista, la sintaxis especial utilizada por Python para completar o llenar listas masivas. | ||
+ | |||
+ | Una comprensión de lista es en realidad una lista, pero **se creó sobre la marcha durante la ejecución del programa, y no se describe de forma estática**. | ||
+ | |||
+ | Echa un vistazo al fragmento: | ||
+ | |||
+ | row = [WHITE_PAWN for i in range(8)] | ||
+ | |||
+ | |||
+ | La parte del código colocada dentro de los paréntesis especifica: | ||
+ | |||
+ | * Los datos que se utilizarán para completar la lista (WHITE_PAWN) | ||
+ | * La cláusula que especifica cuántas veces se producen los datos dentro de la lista (for i in range(8)) | ||
+ | |||
+ | Permítenos mostrarte otros ejemplos de comprensión de lista: | ||
+ | |||
+ | Ejemplo #1: | ||
+ | <code python> | ||
+ | squares = [x ** 2 for x in range(10)] | ||
+ | </ | ||
+ | |||
+ | El fragmento de código genera una lista de diez elementos y la rellena con cuadrados de diez números enteros que comienzan desde cero (0, 1, 4, 9, 16, 25, 36, 49, 64, 81) | ||
+ | |||
+ | Ejemplo #2: | ||
+ | <code python> | ||
+ | twos = [2 ** i for i in range(8)] | ||
+ | </ | ||
+ | |||
+ | El fragmento crea un arreglo de ocho elementos que contiene las primeras ocho potencias del numero dos (1, 2, 4, 8, 16, 32, 64, 128) | ||
+ | |||
+ | Ejemplo #3: | ||
+ | <code python> | ||
+ | odds = [x for x in squares if x % 2 != 0 ] | ||
+ | </ | ||
+ | |||
+ | El fragmento crea una lista con solo los elementos impares de la lista squares. | ||
+ | |||
+ | === Listas dentro de listas: arreglos bidimensionales | ||
+ | Supongamos también que un símbolo predefinido denominado EMPTY designa un campo vacío en el tablero de ajedrez. | ||
+ | |||
+ | Entonces, si queremos crear una lista de listas que representan todo el tablero de ajedrez, se puede hacer de la siguiente manera: | ||
+ | <code python> | ||
+ | board = [] | ||
+ | |||
+ | for i in range(8): | ||
+ | row = [EMPTY for i in range(8)] | ||
+ | board.append(row) | ||
+ | </ | ||
+ | Nota: | ||
+ | * La parte interior del bucle crea una fila que consta de ocho elementos (cada uno de ellos es igual a EMPTY) y lo agrega a la lista del board. | ||
+ | * La parte exterior se repite ocho veces. | ||
+ | * En total, la lista board consta de 64 elementos (todos iguales a EMPTY). | ||
+ | |||
+ | Este modelo imita perfectamente el tablero de ajedrez real, que en realidad es una lista de elementos de ocho elementos, todos ellos en filas individuales. Resumamos nuestras observaciones: | ||
+ | |||
+ | * Los elementos de las filas son campos, ocho de ellos por fila. | ||
+ | * Los elementos del tablero de ajedrez son filas, ocho de ellos por tablero de ajedrez. | ||
+ | |||
+ | La variable board ahora es un **arreglo bidimensional**. También se le llama, por analogía a los términos algebraicos, | ||
+ | |||
+ | |||
+ | Como las listas de comprensión puede ser anidadas, podemos acortar la creación del tablero de la siguiente manera: | ||
+ | |||
+ | <code python> | ||
+ | board = [[EMPTY for i in range(8)] for j in range(8)] | ||
+ | </ | ||
+ | |||
+ | La parte interna (bucle i) crea una fila, y la parte externa (bucle j) crea una lista de filas. | ||
+ | |||
+ | El acceso al campo seleccionado del tablero requiere dos índices: el primero selecciona la fila; el segundo: el número del campo dentro de la fila, el cual es un número de columna. | ||
+ | |||
+ | Echa un vistazo al tablero de ajedrez. Cada campo contiene un par de índices que se deben dar para acceder al contenido del campo: | ||
+ | {{ : | ||
+ | |||
+ | Echando un vistazo a la figura que se muestra arriba, coloquemos algunas piezas de ajedrez en el tablero. Primero, agreguemos todas las torres: | ||
+ | <code python> | ||
+ | board[0][0] = ROOK | ||
+ | board[0][7] = ROOK | ||
+ | board[7][0] = ROOK | ||
+ | board[7][7] = ROOK | ||
+ | </ | ||
+ | Si deseas agregar un caballo a C4, hazlo de la siguiente manera: | ||
+ | <code python> | ||
+ | board[4][2] = KNIGHT | ||
+ | </ | ||
+ | |||
+ | === Naturaleza multidimensional de las listas: aplicaciones avanzadas | ||
+ | Profundicemos en la naturaleza multidimensional de las listas. Para encontrar cualquier elemento de una lista bidimensional, | ||
+ | |||
+ | Una vertical (número de fila). | ||
+ | Una horizontal (número de columna). | ||
+ | Imagina que desarrollas una pieza de software para una estación meteorológica automática. El dispositivo registra la temperatura del aire cada hora y lo hace durante todo el mes. Esto te da un total de 24 × 31 = 744 valores. Intentemos diseñar una lista capaz de almacenar todos estos resultados. | ||
+ | |||
+ | Primero, debes decidir qué tipo de datos sería adecuado para esta aplicación. En este caso, sería mejor un float, ya que este termómetro puede medir la temperatura con una precisión de 0.1 ℃. | ||
+ | |||
+ | Luego tomarás la decisión arbitraria de que las filas registrarán las lecturas cada hora exactamente (por lo que la fila tendrá 24 elementos) y cada una de las filas se asignará a un día del mes (supongamos que cada mes tiene 31 días, por lo que necesita 31 filas). Aquí está el par apropiado de comprensiones(h es para las horas, dpara el día): | ||
+ | |||
+ | <code python> | ||
+ | temps = [[0.0 for h in range(24)] for d in range(31)] | ||
+ | </ | ||
+ | |||
+ | Toda la matriz está llena de ceros ahora. Puede suponer que se actualiza automáticamente utilizando agentes de hardware especiales. Lo que tienes que hacer es esperar a que la matriz se llene con las mediciones. | ||
+ | |||
+ | Ahora es el momento de determinar la temperatura promedio mensual del mediodía. Suma las 31 lecturas registradas al mediodía y divida la suma por 31. Puedes suponer que la temperatura de medianoche se almacena primero. Aquí está el código: | ||
+ | <code python> | ||
+ | temps = [[0.0 for h in range(24)] for d in range(31)] | ||
+ | # | ||
+ | # La matriz se actualiza aquí. | ||
+ | # | ||
+ | |||
+ | total = 0.0 | ||
+ | |||
+ | for day in temps: | ||
+ | total += day[11] | ||
+ | |||
+ | average = total / 31 | ||
+ | |||
+ | print(" | ||
+ | </ | ||
+ | Nota: La variable day utilizada por el bucle for no es un escalar: cada paso a través de la matriz temps lo asigna a la siguiente fila de la matriz; Por lo tanto, es una lista. Se debe indexar con 11 para acceder al valor de temperatura medida al mediodía. | ||
+ | |||
+ | Ahora encuentra la temperatura más alta durante todo el mes, analiza el código: | ||
+ | <code python> | ||
+ | temps = [[0.0 for h in range(24)] for d in range(31)] | ||
+ | # | ||
+ | # La matriz se actualiza aquí. | ||
+ | # | ||
+ | |||
+ | highest = -100.0 | ||
+ | |||
+ | for day in temps: | ||
+ | for temp in day: | ||
+ | if temp > highest: | ||
+ | highest = temp | ||
+ | |||
+ | print(" | ||
+ | </ | ||
+ | Nota: | ||
+ | * La variable day itera en todas las filas de la matriz temps. | ||
+ | * La variable temp itera a través de todas las mediciones tomadas en un día. | ||
+ | |||
+ | === Arreglos tridimensionales | ||
+ | Python no limita la profundidad de la inclusión lista en lista. Aquí puedes ver un ejemplo de un arreglo tridimensional: | ||
+ | |||
+ | Imagina un hotel. Es un hotel enorme que consta de tres edificios, de 15 pisos cada uno. Hay 20 habitaciones en cada piso. Para esto, necesitas un arreglo que pueda recopilar y procesar información sobre las habitaciones ocupadas/ | ||
+ | |||
+ | Primer paso: El tipo de elementos del arreglo. En este caso, sería un valor Booleano (True/ | ||
+ | |||
+ | Paso dos: análisis de la situación. Resume la información disponible: tres edificios, 15 pisos, 20 habitaciones. | ||
+ | |||
+ | Ahora puedes crear el arreglo: | ||
+ | <code python> | ||
+ | rooms = [[[False for r in range(20)] for f in range(15)] for t in range(3)] | ||
+ | </ | ||
+ | |||
+ | El primer índice (0 a 2) selecciona uno de los edificios; el segundo (0 a 14) selecciona el piso, el tercero (0 a 19) selecciona el número de habitación. Todas las habitaciones están inicialmente desocupadas. | ||
+ | |||
+ | Ahora ya puedes reservar una habitación para dos recién casados: en el segundo edificio, en el décimo piso, habitación 14: | ||
+ | <code python> | ||
+ | rooms[1][9][13] = True | ||
+ | </ | ||
+ | |||
+ | y desocupar el segundo cuarto en el quinto piso ubicado en el primer edificio: | ||
+ | <code python> | ||
+ | rooms[0][4][1] = False | ||
+ | </ | ||
+ | |||
+ | Verifica si hay disponibilidad en el piso 15 del tercer edificio: | ||
+ | <code python> | ||
+ | vacancy = 0 | ||
+ | |||
+ | for room_number in range(20): | ||
+ | if not rooms[2][14][room_number]: | ||
+ | vacancy += 1 | ||
+ | </ | ||
+ | |||
+ | La variable vacancy contiene 0 si todas las habitaciones están ocupadas, o en dado caso el número de habitaciones disponibles. | ||
+ |