MÓDULO 3

Valores booleanos, ejecución condicional, bucles, listas y su procesamiento, operadores lógicos

¿Qué aprenderás en este módulo?

1. Fundamentos de Python.

2. Pseudocódigo y Bucles en Python.

3. Operaciones lógicas (and, or, not).

4. Listas - colecciones de datos.

5. Ordenando listas simples.

6. Operaciones en listas.

7. Listas en aplicaciones avanzadas.

Descarga el archivo para seguir la clase en Jupyter:

Descargar Archivo

1. Fundamentos de Python

Igualdad: El operador igual a (==)

¿Son dos valores iguales?

Para hacer esta pregunta, se utiiza el == operador (igual igual).

No olvides esta importante distinción:

= es un operador de asignación, por ejemplo, a=b asigna a la variable a el valor de b.

== es una pregunta ¿son estos valores iguales? así que a==b compara a y b.

Es un operador binario con enlazado del lado izquierdo. Necesita dos argumentos y verifica si son iguales.

2 == 2

True

1 == 2

False

El operador == (igual a) compara los valores de dos operandos. Si son iguales, el resultado de la comparación es True. Si no son iguales, el resultado de la comparación es False.

Observa la comparación de igualdad a continuación: ¿Cuál es el resultado de esta operación?

var == 0

Toma en cuenta que no podemos encontrar la respuesta si no sabemos qué valor está almacenado actualmente en la variable var.

Si la variable se ha cambiado muchas veces durante la ejecución del programa, o si se ingresa su valor inicial desde la consola, Python solo puede responder a esta pregunta en el tiempo de ejecución del programa.

Entonces, vamos a practicar la comprensión del operador == ¿Puedes adivinar la salida del código a continuación?

var = 0   # asignando 0 a var
print(var == 0)

var = 1  # asignando 1 a var
print(var == 0)

Ejecuta el código y comprueba si tenías razón.

True
False

Desigualdad: El operador no es igual a (!=)

El operador != (no es igual a) también compara los valores de dos operandos. Aquí está la diferencia: si son iguales, el resultado de la comparación es False. Si no son iguales, el resultado de la comparación es True.

Ahora echa un vistazo a la comparación de desigualdad a continuación: ¿Puedes adivinar el resultado de esta operación?

var = 0 # asignando 0 a var
print(var != 0)

var = 1 # asignando 1 a var
print(var != 0)

Ejecuta el código y comprueba si tenías razón.

False
True

Operadores de comparación: mayor que

También se puede hacer una pregunta de comparación usando el operador > (mayor que).

Ejemplo. Si deseas saber si hay más ovejas negras que blancas, puedes escribirlo de la siguiente manera:

black_sheep = 10
white_sheep = 8
black_sheep > white_sheep  # mayor que

True

Recuerda: True lo confirma; False lo niega.

Operadores de comparación: mayor o igual que

El operador mayor que tiene otra variante especial, una variante no estricta, pero se denota de manera diferente que la notación aritmética clásica: >= (mayor o igual que).

Hay dos signos subsecuentes, no uno.

Ambos operadores (estrictos y no estrictos), así como los otros dos que se analizan en la siguiente sección, son operadores binarios con enlace del lado izquierdo, y su prioridad es mayor que la mostrada por == y !=. Ejemplo:

cuadrado = 4
triangulo = 3
rectangulo = 4

cuadrado >= triangulo

True

cuadrado >= rectangulo

True

triangulo >= rectangulo

False

Operadores de comparación: menor o igual que

Como probablemente ya hayas adivinado, los operadores utilizados en este caso son: El operador < (menor que) y su hermano no estricto: <= (menor o igual que). Volvamos al ejemplo anterior:

cuadrado <= triangulo

False

cuadrado <= rectangulo

True

triangulo <= rectangulo

True

Condiciones y ejecución condicional

Ya sabes como hacer preguntas a Python, pero aún no sabes como hacer un uso razonable de las respuestas. Se debe tener un mecanismo que le permita hacer algo si se cumple una condición, y no hacerlo si no se cumple.

Para tomar tales decisiones, Python ofrece una instrucción especial. Debido a su naturaleza y su aplicación, se denomina instrucción condicional (o sentencia condicional).

Existen varias variantes de la misma. La primera forma de una sentencia condicional, que puede ver a continuación, está escrita de manera muy informal pero figurada:

if true_or_not:
    do_this_if_true

¿Cómo funciona esta sentencia?

Si la expresión true_or_not representa la verdad (es decir, su valor no es igual a cero), las sentencias con sangría se ejecutarán.

Si la expresión true_or_not no representa la verdad (es decir, su valor es igual a cero), las sentencias con sangría se omitirán, y la siguiente instrucción ejecutada será la siguiente al nivel de la sangría original.

Ejecución condicional: la sentencia if

Hemos dicho que las sentencias condicionales deben tener sangría. Esto crea una estructura muy legible, demostrando claramente todas las rutas de ejecución posibles en el código.

x = 10

if x >=10:
    y = 20
print(y)

20

¿Cuál crees que sea el resultado del siguiente código?

a = 10

if a >=11:
    b = 25
print(b)

Ahora vamos a discutir otra variante de la sentencia condicional, que también permite realizar una acción adicional cuando no se cumple la condición.

Ejecución condicional: la sentencia if-else

Las sentencias if-else son estructuras de control que nos permiten tomar decisiones en nuestro código basadas en ciertas condiciones.

La parte del código que comienza con else dice qué hacer si no se cumple la condición especificada por el if (observa los dos puntos después de la palabra).

a = 10

if a >=11:
    b = 25
else:
    b = 50
print(b)

50

Sentencias if-else anidadas

A veces necesitamos tomar decisiones más complejas. Para ello, podemos anidar sentencias if-else, es decir, colocar una sentencia if-else dentro de otra.

edad = 20
if edad < 18:
    print("Eres menor de edad.")
else:
    if edad < 65:
        print("Eres adulto.")
    else:
        print("Eres un adulto mayor.")

Eres adulto.

La sentencia elif

Para mejorar la legibilidad de nuestro código, podemos usar elif (una combinación de else e if) en lugar de anidar tantas sentencias if-else.

Ejemplo:

puntaje = 85

if puntaje >= 90:
    print("Excelente")
elif puntaje >= 75:
    print("Bueno")
elif puntaje >= 50:
    print("Aprobado")
else:
    print("Reprobado")

Bueno

La forma de ensamblar las siguientes sentencias if-elif-else a veces se denomina cascada.

Veámos un ejemplo con todos los casos vistos:

x = 10

if x > 5:  # True
    if x == 6:  # False
        print("anidado: x == 6")
    elif x == 10:  # True
        print("anidado: x == 10")
    else:
        print("anidado: else")
else:
    print("else")

anidado: x == 10

Ejercicio: Escribe un programa que determine si un número es positivo, negativo o cero y además si es par o impar.

numero = -3

if numero > 0:
    print("El número es positivo.")
    if numero % 2 == 0:
        print("Y es par.")
    else:
        print("Y es impar.")
elif numero < 0:
    print("El número es negativo.")
    if numero % 2 == 0:
        print("Y es par.")
    else:
        print("Y es impar.")
else:
    print("El número es cero.")

El número es negativo.
Y es impar.

2. Pseudocódigo y Bucles en Python.

¿Qué es el Pseudocódigo?

El pseudocódigo es una descripción de alto nivel de un algoritmo que usa una mezcla de lenguaje natural y estructuras de control de programación. No sigue la sintaxis de un lenguaje de programación específico, pero proporciona una guía clara de cómo se debe estructurar el código.

Ventajas del Pseudocódigo:

Claridad: Ayuda a entender la lógica del programa sin preocuparse por la sintaxis específica de un lenguaje.

Planificación: Permite planificar y diseñar algoritmos antes de implementarlos en código real.

Comunicación: Facilita la comunicación de ideas entre programadores y no programadores.

Ahora revisemos un ejemplo sencillo:

Inicio
    Leer número1
    Leer número2
    Si número1 > número2 Entonces
        Imprimir "Número1 es mayor"
    Sino
        Imprimir "Número2 es mayor o ambos son iguales"
Fin

Pensemos un caso más complejo.

¿Qué sucede si te pedimos que escribas un programa que encuentre el mayor de doscientos números? ¿Te imaginas el código?.

Necesitarás doscientas variables. Si doscientas variables no son lo suficientemente complicadas, intenta imaginar la búsqueda del número más grande de un millón.

Imagina un código que contiene 199 sentencias condicionales y doscientas invocaciones de la función input(). Por suerte, no necesitas lidiar con eso. Hay un enfoque más simple.

Por ahora ignoraremos los requisitos de la sintaxis de Python e intentaremos analizar el problema sin pensar en la programación real. En otras palabras, intentaremos escribir el algoritmo, y cuando estemos contentos con él, lo implementaremos.

Veamos nuestro pseudocódigo a continuación:

largest_number = -999999999
number = int(input())
if number == -1:
    print(largest_number)
    exit()
if number > largest_number:
    largest_number = number
# Ir a la línea 02

¿Qué está pasando en él?

En primer lugar, podemos simplificar el programa si, al principio del código, le asignamos a la variable largest_number un valor que será más pequeño que cualquiera de los números ingresados. Usaremos -999999999 para ese propósito.

En segundo lugar, asumimos que nuestro algoritmo no sabrá por adelantado cuántos números se entregarán al programa. Esperamos que el usuario ingrese todos los números que desee; el algoritmo funcionará bien con cien y con mil números. ¿Cómo hacemos eso?.

Hacemos un trato con el usuario: cuando se ingresa el valor -1, será una señal de que no hay más datos y que el programa debe finalizar su trabajo.

De lo contrario, si el valor ingresado no es igual a -1, el programa leerá otro número, y así sucesivamente.

El truco se basa en la suposición de que cualquier parte del código se puede realizar más de una vez, precisamente, tantas veces como sea necesario.

La ejecución de una determinada parte del código más de una vez se denomina bucle.

Bucles en Python

Bucles (ciclos) en el código con while


mientras haya algo que hacer
    hazlo

Toma en cuenta que este registro también declara que, si no hay nada que hacer, nada ocurrirá.

En general, en Python, un bucle se puede representar de la siguiente manera:

while conditional_expression:
    instruction

Si observas algunas similitudes con la instrucción if, está bien. De hecho, la diferencia sintáctica es solo una: usa la palabra while en lugar de la palabra if.

La diferencia semántica es más importante: cuando se cumple la condición, if realiza sus sentencias sólo una vez; while repite la ejecución siempre que la condición se evalúe como True.

Nota: todas las reglas relacionadas con sangría también se aplican aquí.

Observa el algoritmo a continuación:

while conditional_expression:
    instruction_one
    instruction_two
    instruction_three
    :
    :
    instruction_n

Ahora, es importante recordar que:

→ Si deseas ejecutar más de una sentencia dentro de un while, debes (como con if) poner sangría a todas las instrucciones de la misma manera.

→ Una instrucción o conjunto de instrucciones ejecutadas dentro del while se llama el cuerpo del bucle.

→ Si la condición es False (igual a cero) tan pronto como se compruebe por primera vez, el cuerpo no se ejecuta ni una sola vez (ten en cuenta la analogía de no tener que hacer nada si no hay nada que hacer).

→ El cuerpo debe poder cambiar el valor de la condición, porque si la condición es True al principio, el cuerpo podría funcionar continuamente hasta el infinito. Observa que hacer una cosa generalmente disminuye la cantidad de cosas por hacer.

Un bucle infinito

Un bucle infinito, también denominado bucle sin fin, es una secuencia de instrucciones en un programa que se repite indefinidamente (bucle sin fin).

Este es un ejemplo de un bucle que no puede finalizar su ejecución:

while True:
    print("Estoy atrapado dentro de un bucle.")

Estoy atrapado dentro de un bucle.
Estoy atrapado dentro de un bucle.
Estoy atrapado dentro de un bucle.
Estoy atrapado dentro de un bucle.
Estoy atrapado dentro de un bucle.
Estoy atrapado dentro de un bucle.
Estoy atrapado dentro de un bucle.
Estoy atrapado dentro de un bucle.
Estoy atrapado dentro de un bucle.
Estoy atrapado dentro de un bucle.
Estoy atrapado dentro de un bucle.
.
.
.

Analiza el siguiente programa cuidadosamente. Localiza donde comienza el bucle (línea 8) y descubre cómo se sale del cuerpo del bucle:

# Almacena el actual número más grande aquí.
largest_number = -999999999

# Ingresa el primer valor.
number = int(input("Ingresa un número ó -1 para detener: "))

# Si el número no es igual a -1, continuaremos
while number != -1:
    # ¿Es el número más grande que el valor de largest_number?
    if number > largest_number:
        # Sí si, se actualiza largest_number.
        largest_number = number
    # Ingresa el siguiente número.
    number = int(input("Ingresa un número ó -1 para detener: "))

# Imprime el número más grande
print("El número más grande es:", largest_number)

Comprueba cómo este código implementa el algoritmo que te mostramos anteriormente.

Introduce un número o escribe -1 para detener: 10
Introduce un número o escribe -1 para detener: 5
Introduce un número o escribe -1 para detener: 2
Introduce un número o escribe -1 para detener: 0
Introduce un número o escribe -1 para detener: -5
Introduce un número o escribe -1 para detener: -1
El número más grande es: 10

Empleando una variable counter para salir del bucle

Observa el fragmento de código a continuación:

counter = 10
while counter != 0:
    print("Dentro del bucle.", counter)
    counter -= 1
print("Fuera del bucle.", counter)

Dentro del bucle. 10
Dentro del bucle. 9
Dentro del bucle. 8
Dentro del bucle. 7
Dentro del bucle. 6
Dentro del bucle. 5
Dentro del bucle. 4
Dentro del bucle. 3
Dentro del bucle. 2
Dentro del bucle. 1
Fuera del bucle. 0

Este código está destinado a imprimir la cadena "Dentro del bucle." y el valor almacenado en la variable counter durante un bucle dado exactamente cinco veces. Una vez que la condición se haya cumplido (la variable counter ha alcanzado 0), se sale del bucle y aparece el mensaje "Fuera del bucle". así como tambien el valor almacenado en counter se imprime.

Pero hay una cosa que se puede escribir de forma más compacta: la condición del bucle while.

Observa la diferencia:

counter = 10
while counter:
    print("Dentro del bucle.", counter)
    counter -= 1
print("Fuera del bucle.", counter)

Dentro del bucle. 10
Dentro del bucle. 9
Dentro del bucle. 8
Dentro del bucle. 7
Dentro del bucle. 6
Dentro del bucle. 5
Dentro del bucle. 4
Dentro del bucle. 3
Dentro del bucle. 2
Dentro del bucle. 1
Fuera del bucle. 0

¿Es más compacto que antes? Un poco. ¿Es más legible? Eso es discutible.

Bucles con for

Otro tipo de bucle disponible en Python proviene de la observación de que a veces es más importante contar los "giros o vueltas" del bucle que verificar las condiciones.

Imagina que el cuerpo de un bucle debe ejecutarse exactamente cien veces. Si deseas utilizar el bucle while para hacerlo, puede tener este aspecto:

i = 0
while i < 10:
    print("hola mundo!")
    i += 1

hola mundo!
hola mundo!
hola mundo!
hola mundo!
hola mundo!
hola mundo!
hola mundo!
hola mundo!
hola mundo!
hola mundo!

El bucle for está diseñado para realizar tareas más complicadas, puede "explorar" grandes colecciones de datos elemento por elemento. Te mostraremos como hacerlo pronto, pero ahora presentaremos una variante más sencilla de su aplicación.

for i in range(10):
    print("hola mundo!")
    pass

hola mundo!
hola mundo!
hola mundo!
hola mundo!
hola mundo!
hola mundo!
hola mundo!
hola mundo!
hola mundo!
hola mundo!

Existen algunos elementos nuevos:

→ La palabra reservada for abre el bucle for; nota - No hay condición después de eso; no tienes que pensar en las condiciones, ya que se verifican internamente, sin ninguna intervención.

→ Cualquier variable después de la palabra reservada for es la variable de control del bucle; cuenta los giros del bucle y lo hace automáticamente.

→ La palabra reservada in introduce un elemento de sintaxis que describe el rango de valores posibles que se asignan a la variable de control.

→ La función range() (esta es una función muy especial) es responsable de generar todos los valores deseados de la variable de control; en nuestro ejemplo, la función creará (incluso podemos decir que alimentará el bucle con) valores subsiguientes del siguiente conjunto: 0, 1, 2 .. 97, 98, 99; nota: en este caso, la función range() comienza su trabajo desde 0 y lo finaliza un paso (un número entero) antes del valor de su argumento.

→ Nota la palabra clave pass dentro del cuerpo del bucle - no hace nada en absoluto; es una instrucción vacía: la colocamos aquí porque la sintaxis del bucle for exige al menos una instrucción dentro del cuerpo (por cierto, if, elif, else y while expresan lo mismo).

Ahora echa un vistazo al fragmento siguiente:

for i in range(10):
    print("El valor de i es actualmente", i)

El valor de i es actualmente 0
El valor de i es actualmente 1
El valor de i es actualmente 2
El valor de i es actualmente 3
El valor de i es actualmente 4
El valor de i es actualmente 5
El valor de i es actualmente 6
El valor de i es actualmente 7
El valor de i es actualmente 8
El valor de i es actualmente 9

Nota lo siguiente:

→ El bucle se ha ejecutado diez veces (es el argumento de la función range()).

→ El valor de la última variable de control es 9 (no 10, ya que comienza desde 0, no desde 1).

La invocación de la función range() puede estar equipada con dos argumentos, no solo uno:

for i in range(2, 8):
    print("El valor de i es actualmente", i)

El valor de i es actualmente 2
El valor de i es actualmente 3
El valor de i es actualmente 4
El valor de i es actualmente 5
El valor de i es actualmente 6
El valor de i es actualmente 7

En este caso, el primer argumento determina el valor inicial (primero) de la variable de control.

El último argumento muestra el primer valor que no se asignará a la variable de control.

Nota: la función range() solo acepta enteros como argumentos y genera secuencias de enteros.

La función range() también puede aceptar tres argumentos:

for i in range(2, 9, 3):
    print("El valor de i es actualmente", i)

El valor de i es actualmente 2
El valor de i es actualmente 5
El valor de i es actualmente 8

El tercer argumento es un incremento: es un valor agregado para controlar la variable en cada giro del bucle (como puedes sospechar, el valor predeterminado del incremento es 1).

Las sentencias break y continue

Hasta ahora, hemos tratado el cuerpo del bucle como una secuencia indivisible e inseparable de instrucciones que se realizan completamente en cada giro del bucle. Sin embargo, como desarrollador, podrías enfrentar las siguientes opciones:

sentencia break

La sentencia break se utiliza para salir de un bucle prematuramente, es decir, cuando se cumple una condición específica. Esto significa que el bucle se detiene inmediatamente y el control del programa pasa a la siguiente instrucción después del bucle.

Ejemplo de break:

for i in range(1, 11):
    if i == 5:
        break
    print(i)

1
2
3
4

En este ejemplo, el bucle for se detiene cuando i es igual a 5 debido a la sentencia break.

sentencia continue

La sentencia continue se utiliza para omitir el resto del código dentro de un bucle para la iteración actual y pasar a la siguiente iteración. En otras palabras, salta el resto del código en esa iteración y continúa con la siguiente.

Ejemplo de continue:

for i in range(1, 11):
    if i == 5:
        continue
    print(i)

1
2
3
4
6
7
8
9
10

En este ejemplo, cuando i es igual a 5, la sentencia continue omite la instrucción print(i) y pasa a la siguiente iteración del bucle.

Ejercicio:

Escribe un programa que lea una lista de números del usuario y detenga la lectura si se introduce el número 0, pero omita cualquier número negativo.

Pseudocódigo:

Inicio
    Mientras Verdadero
        Leer número del usuario
        Si el número es 0
            Romper el bucle
        Si el número es negativo
            Continuar con la siguiente iteración
        Imprimir el número
Fin

Código en Python:

while True:
    numero = int(input("Introduce un número (0 para terminar): "))
    if numero == 0:
        break
    if numero < 0:
        continue
    print(f"Has introducido: {numero}")

El bucle while y la rama else

Como pudiste haber sospechado, los bucles también pueden tener la rama else, como los if.

La rama else del bucle siempre se ejecuta una vez, independientemente de si el bucle ha entrado o no en su cuerpo.

i = 1
while i < 5:
    print(i)
    i += 1
else:
    print("else:", i)

1
2
3
4
else: 5

El bucle for y la rama else

Hagamos un ejemplo que tenga la misma salida del ejercicio anterior con while, pero ahora con for.

for i in range(1, 5):
    print(i)
else:
    print("else:", i+1)

1
2
3
4
else: 5

3. Operaciones lógicas (and, or, not).

Lógica de computadora

¿Te has dado cuenta de que las condiciones que hemos usado hasta ahora han sido muy simples, por no decir, bastante primitivas? Las condiciones que utilizamos en la vida real son mucho más complejas. Veamos este enunciado:

Si tenemos tiempo libre, y el clima es bueno, saldremos a caminar.

Hemos utilizado la conjunción and (y), lo que significa que salir a caminar depende del cumplimiento simultáneo de estas dos condiciones. En el lenguaje de la lógica, tal conexión de condiciones se denomina conjunción. Y ahora otro ejemplo:

Si tu estás en el centro comercial o yo estoy en el centro comercial, uno de nosotros le comprará un regalo a mamá.

La aparición de la palabra or (o) significa que la compra depende de al menos una de estas condiciones. En lógica, este compuesto se llama una disyunción.

Está claro que Python debe tener operadores para construir conjunciones y disyunciones. Sin ellos, el poder expresivo del lenguaje se debilitaría sustancialmente. Se llaman operadores lógicos.

and

Un operador de conjunción lógica en Python es la palabra and. Es un operador binario con una prioridad inferior a la expresada por los operadores de comparación. Nos permite codificar condiciones complejas sin el uso de paréntesis como este:

numero = 15

if numero >= 10 and numero <= 20:
    print(f"El número {numero} está entre 10 y 20.")
else:
    print(f"El número {numero} no está entre 10 y 20.")

El número 15 está entre 10 y 20.

El resultado proporcionado por el operador and se puede determinar sobre la base de la tabla de verdad.

Si consideramos la conjunción de A and B, el conjunto de valores posibles de argumentos y los valores correspondientes de conjunción se ve de la siguiente manera:

Dancer

or

Un operador de disyunción es la palabra or. Es un operador binario con una prioridad más baja que and (al igual que + en comparación con *). Su tabla de verdad es la siguiente:

Dancer

Veámos el siguiente ejemplo:

numero = 25

if numero < 10 or numero > 20:
    print(f"El número {numero} está fuera del rango 10 - 20.")
else:
    print(f"El número {numero} está dentro del rango 10 - 20.")

El número 25 está fuera del rango de 10 a 20.

not

Además, hay otro operador que se puede aplicar para condiciones de construcción. Es un operador unario que realiza una negación lógica. Su funcionamiento es simple: convierte la verdad en falso y lo falso en verdad.

Este operador se escribe como la palabra not, y su prioridad es muy alta: igual que el unario + y -. Su tabla de verdad es simple:

Dancer

Ejemplo:

edad = 16

if not (edad >= 18):
    print("La persona es menor de edad.")
else:
    print("La persona es mayor de edad.")

La persona es menor de edad.

4. Listas - colecciones de datos.

Funciones frente a métodos

Un método es un tipo específico de función: se comporta como una función y se parece a una función, pero difiere en la forma en que actúa y en su estilo de invocación.

Una función no pertenece a ningún dato: obtiene datos, puede crear nuevos datos y (generalmente) produce un resultado.

Un método es propiedad de los datos para los que trabaja, mientras que una función es propiedad de todo el código.

Esto también significa que invocar un método requiere alguna especificación de los datos a partir de los cuales se invoca el método.

En general, una invocación de función típica puede tener este aspecto:

result = function(arg)

La función toma un argumento, hace algo y devuelve un resultado.

Una invocación de un método típico usualmente se ve así:

result = data.method(arg)

Nota: el nombre del método está precedido por el nombre de los datos que posee el método. A continuación, se agrega un punto, seguido del nombre del método y un par de paréntesis que encierran los argumentos.

El método se comportará como una función, pero puede hacer algo más: puede cambiar el estado interno de los datos a partir de los cuales se ha invocado.

¿Por qué necesitamos listas?

Hasta ahora, has aprendido como declarar variables que pueden almacenar exactamente un valor dado a la vez. Tales variables a veces se denominan escalares por analogía con las matemáticas. Todas las variables que has usado hasta ahora son realmente escalares.

Piensa en lo conveniente que sería declarar una variable que podría almacenar más de un valor. Por ejemplo, cien, o mil o incluso diez mil. Todavía sería una y la misma variable, pero muy amplia y espaciosa. ¿Suena atractivo? Quizás, pero ¿cómo manejarías un contenedor así lleno de valores diferentes? ¿Cómo elegirías solo el que necesitas?

Una lista en Python es una colección de elementos que pueden ser de diferentes tipos (enteros, cadenas, objetos, etc.). Las listas son mutables, lo que significa que sus elementos se pueden cambiar después de que la lista ha sido creada. Las listas se definen usando corchetes [], y los elementos dentro de la lista se separan por comas.

Vamos a crear una variable llamada numeros; se le asigna no solo un número, sino que se llena con una lista que consta de cinco valores:

# Crear una lista de números
numeros = [10, 20, 30, 40, 50]

# Imprimir la lista completa
print("Lista original:", numeros)

Lista original: [10, 20, 30, 40, 50]

Agregar un número al final de la lista con append():

Un nuevo elemento puede ser añadido al final de la lista existente. Dicha operación se realiza mediante un método llamado append(). Toma el valor de su argumento y lo coloca al final de la lista que posee el método.

# Agregar un número al final de la lista
numeros.append(60)
print("Después de agregar 60:", numeros)

Después de agregar 60: [10, 20, 30, 40, 50, 60]

Eliminar un número de la lista con remove():

# Eliminar un número de la lista
numeros.remove(30)
print("Después de eliminar 30:", numeros)

Después de eliminar 30: [10, 20, 40, 50, 60]

Acceder al primer y último elemento de la lista:

# Acceder al primer y último elemento de la lista
print("Primer elemento:", numeros[0])
print("Último elemento:", numeros[-1])

Primer elemento: 10
Último elemento: 60

Python ha adoptado una convención que indica que los elementos de una lista están siempre numerados desde cero. Esto significa que el elemento almacenado al principio de la lista tendrá el número cero.

Antes de continuar, debemos indicar lo siguiente: nuestra lista es una colección de elementos, pero cada elemento es un escalar.

La función len()

La longitud de una lista puede variar durante la ejecución. Se pueden agregar nuevos elementos a la lista, mientras que otros pueden eliminarse de ella. Esto significa que la lista es una entidad muy dinámica.

Si deseas verificar la longitud actual de la lista, puedes usar una función llamada len() (su nombre proviene de length - longitud).

La función toma el nombre de la lista como un argumento y devuelve el número de elementos almacenados actualmente dentro de la lista (en otras palabras, la longitud de la lista).

# Imprimiendo la longitud de la lista.
print("Longitud de la lista:", len(numeros))

Longitud de la lista: 5

Eliminando elementos de una lista del

Cualquier elemento de la lista puede ser eliminado en cualquier momento, esto se hace con una instrucción llamada del (eliminar). Nota: es una instrucción, no una función.

Tienes que apuntar al elemento que quieres eliminar, desaparecerá de la lista y la longitud de la lista se reducirá en uno.

del numeros[1]
print(len(numeros))
print(numeros)

4
[10, 40, 50, 60]

Los índices negativos son válidos

Puede parecer extraño, pero los índices negativos son válidos y pueden ser muy útiles.

Como hemos visto en el ejemplo anterior, un elemento con un índice igual a -1 es el último en la lista.

Del mismo modo, el elemento con un índice igual a -2 es el anterior al último en la lista.

print(numeros[-2])

50

Agregando elementos a una lista: insert()

El método insert() es un poco más inteligente: puede agregar un nuevo elemento en cualquier lugar de la lista, no solo al final.

numeros.insert(1, 25)
print(numeros)

[10, 25, 40, 50, 60]

Ejercicio: iniciar una lista vacía y agregar nuevos elementos con insert().

my_list = []  # Creando una lista vacía.

for i in range(5):
    my_list.insert(0, i + 1)

print(my_list)

[5, 4, 3, 2, 1]

Ejercicio: iniciar una lista vacía y agregar nuevos elementos con append().

my_list = []  # Creando una lista vacía.

for i in range(5):
    my_list.append(i + 1)

print(my_list)

[1, 2, 3, 4, 5]

Obtendremos la misma secuencia, pero en orden inverso.


5. Ordenando listas simples.

Ordenamiento burbuja

Por simplicidad, digamos que una lista se puede ordenar de dos maneras:

→ Ascendente (o más precisamente, no descendente): si en cada par de elementos adyacentes, el primer elemento no es mayor que el segundo.

→ Descendente (o más precisamente, no ascendente): si en cada par de elementos adyacentes, el primer elemento no es menor que el segundo.

Observa la siguiente lista de números: 8, 10, 6, 2, 4.

Intentaremos utilizar el siguiente enfoque: tomaremos el primer y el segundo elemento y los compararemos; si determinamos que están en el orden incorrecto (es decir, el primero es mayor que el segundo), los intercambiaremos; Si su orden es válido, no haremos nada. Un vistazo a nuestra lista confirma lo último: los elementos 01 y 02 están en el orden correcto, así como 8<10.

Ahora observa el segundo y el tercer elemento. Están en las posiciones equivocadas. Tenemos que intercambiarlos: 8, 6, 10, 2, 4.

Vamos más allá y observemos los elementos tercero y cuarto. Una vez más, esto no es lo que se supone que es. Tenemos que intercambiarlos: 8, 6, 2, 10, 4.

Ahora comprobemos los elementos cuarto y quinto. Si, ellos también están en las posiciones equivocadas. Ocurre otro intercambio: 8, 6, 2, 4, 10.

El primer paso a través de la lista ya está terminado. Todavía estamos lejos de terminar nuestro trabajo, pero algo curioso ha sucedido mientras tanto. El elemento más grande, 10, ya ha llegado al final de la lista. Ten en cuenta que este es el lugar deseado para él.

Ahora, por un momento, intenta imaginar la lista de una manera ligeramente diferente, es decir, de esta manera:

Dancer

Observa - El 10 está en la parte superior. Podríamos decir que flotó desde el fondo hasta la superficie, al igual que las burbujas en una copa de champán. El método de clasificación deriva su nombre de la misma observación: se denomina ordenamiento de burbuja.

Ahora comenzamos con el segundo paso a través de la lista. Miramos el primer y el segundo elemento, es necesario un intercambio: 6, 8, 2, 4, 10.

Tiempo para el segundo y tercer elemento: también tenemos que intercambiarlos: 6, 2, 8, 4, 10.

Ahora el tercer y cuarto elementos, y la segunda pasada, se completa, ya que 8 ya está en su lugar: 6, 2, 4, 8, 10.

Comenzamos el siguiente pase inmediatamente. Observe atentamente el primer y el segundo elemento: se necesita otro cambio: 2, 6, 4, 8, 10.

Ahora 6 necesita ir a su lugar. Cambiamos el segundo y el tercer elemento: 2, 4, 6, 8, 10.

La lista ya está ordenada. No tenemos nada más que hacer. Esto es exactamente lo que queremos.

Como se observa, la esencia de este algoritmo es simple: comparamos los elementos adyacentes y, al intercambiar algunos de ellos, logramos nuestro objetivo.

Codifiquemos en Python todas las acciones realizadas durante un solo paso a través de la lista.

Resolvamos este problema de la siguiente manera: introducimos una variable auxiliar, su tarea es observar si se ha realizado algún intercambio durante el pase o no. Si no hay intercambio, entonces la lista ya está ordenada, y no hay que hacer nada más. Creamos una variable llamada swapped, y le asignamos un valor de False para indicar que no hay intercambios. De lo contrario, se le asignará True.

my_list = [8, 10, 6, 2, 4]  # lista a ordenar
# Inicia verdadero (True) para ingresar al bucle while.
swapped = True  

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)

[2, 4, 6, 8, 10]

Método sort()

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:

Orden ascendente

El método sort() sin argumentos ordena la lista en orden ascendente.

my_list = [8, 10, 6, 2, 4]
my_list.sort()
print(my_list)

[2, 4, 6, 8, 10]

Orden descendente

Para ordenar la lista en orden descendente, se puede utilizar el argumento reverse=True con el método sort().

my_list = [8, 10, 6, 2, 4]
my_list.sort(reverse=True)
print(my_list)

[10, 8, 6, 4, 2]

Como puedes ver, todas las listas tienen un método denominado sort(), que las ordena lo más rápido posible.

Finalmente, analiza los siguientes ejemplos de esta sección:

lst = ["D", "F", "A", "Z"]
lst.sort()

print(lst)

['A', 'D', 'F', 'Z']

lst = ["D", "F", "A", "Z"]
lst.sort(reverse=True)

print(lst)

['Z', 'F', 'D', 'A']

6. Operaciones con listas.

Interior de las listas

Debemos señalar una característica muy importante de las listas, que las distingue de las variables ordinarias. Omitir tal característica puede afectar tus programas futuros y causar graves problemas si se olvida o se pasa por alto.

Observa el siguiente fragmento de código:

list_1 = [1]
list_2 = list_1
list_1[0] = 2
print(list_2)

[2]

Nota 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).

Podemos aseverar lo siguiente:

→ 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.

Rebanadas

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.

Echa un vistazo a los fragmentos de código a continuación:

Copiando una lista entera:

list_1 = [1]
list_2 = list_1[:]
list_1[0] = 2
print(list_2)

[1]

Esta parte no visible del código descrito como [:] puede producir una lista completamente nueva.

Copiando parte de la lista:

my_list = [10, 8, 6, 4, 2]
new_list = my_list[1:3]
print(new_list)

[8, 6]

Una de las formas más generales de la rebanada es la siguiente:

my_list[start:end]

Como puedes ver, se asemeja a la indexación, pero los dos puntos en el interior hacen una gran diferencia.

Para confirmar:

my_list[start:end]

start es el índice del primer elemento incluido en la rebanada.

end es el índice del primer elemento no incluido en la rebanada.

Rebanadas - índices negativos

Así es como los índices negativos funcionan en las rebanadas:

my_list = [10, 8, 6, 4, 2]
new_list = my_list[1:-1]
print(new_list)

[8, 6, 4]

Lista vacía

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:

my_list = [10, 8, 6, 4, 2]
new_list = my_list[-1:1]
print(new_list)

[]

Rebanadas: start

Si omites el start en tu rebanada, se supone que deseas obtener un segmento que comienza en el elemento con índice 0. El código sería de la siguiente forma:

my_list[:end]

Lo anterior es un equivalente más compacto de:

my_list[0:end]

Observa el fragmento de código a continuación:

my_list = [10, 8, 6, 4, 2]
new_list = my_list[:3]
print(new_list)

[10, 8, 6]

Rebanadas: end

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).

my_list[start:]

Lo anterior es un equivalente más compacto de:

my_list[start:len(my_list)]

Ejemplo:

my_list = [10, 8, 6, 4, 2]
new_list = my_list[3:]
print(new_list)

[4, 2]

Rebanadas: del

La instrucción del descrita anteriormente puede eliminar más de un elemento de la lista a la vez, también puede eliminar rebanadas:

my_list = [10, 8, 6, 4, 2]
del my_list[1:3]
print(my_list)

[10, 4, 2]

Nota: En este caso, la rebanada no produce ninguna lista nueva.

También es posible eliminar todos los elementos a la vez:

my_list = [10, 8, 6, 4, 2]
del my_list[:]
print(my_list)

[]

Sin embargo, observa lo que sucede si decidimos eliminar la lista completa y después la tratamos de invocar:

my_list = [10, 8, 6, 4, 2]
del my_list
print(my_list)

NameError: name 'my_list' is not defined

Como se ve, esto no genera una lista vacía, aunque la instrucción del eliminará la lista, no su contenido.

Los operadores in y not in

Python ofrece dos operadores capaces de revisar la lista para verificar si un valor específico está almacenado dentro de la lista o no. Estos operadores son:

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.

Observa el siguiente ejemplo:

my_list = [0, 3, 12, 8, 2]

print(5 in my_list)
print(5 not in my_list)
print(12 in my_list)

False
True
True

7. Listas en aplicaciones avanzadas.

Listas dentro de listas

Las listas pueden constar de escalares (es decir, números) y elementos de una estructura mucho más compleja. Veamos más de cerca el caso en el que los elementos de una lista son listas.

Observa los siguientes ejemplos de comprensión de lista:

Ejemplo 1:

squares = [x ** 2 for x in range(10)]
print(squares)

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

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:

twos = [2 ** i for i in range(8)]

[1, 2, 4, 8, 16, 32, 64, 128]

El fragmento crea un arreglo de ocho elementos que contiene las primeras ocho potencias del numero dos.

Ejemplo 3:

odds = [x for x in squares if x % 2 != 0 ]
print(odds)

[1, 9, 25, 49, 81]

El fragmento crea una lista con solo los elementos impares de la lista squares.

Dancer

Arreglos bidimensionales

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.

Supongamos también que un símbolo predefinido denominado EMPTY designa un campo vacío en el tablero de ajedrez.

Si queremos crear una lista de listas que representan todo el tablero de ajedrez, se puede hacer de la siguiente manera:

EMPTY = "-"
PAWN = "PEON"
ROOK = "TORRE"
KNIGHT = "CABALLO"

board = []

for i in range(8):
    row = [EMPTY for i in range(8)]
    board.append(row)
print(board)

→ 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).

Ejecuta el código y observa el resultado.

La variable board ahora es un arreglo bidimensional. También se le llama, por analogía a los términos algebraicos, una matriz.

Echando un vistazo a la figura que se muestra arriba, coloquemos algunas piezas de ajedrez en el tablero. Primero, agreguemos todas las torres:

board[0][0] = ROOK
board[0][7] = ROOK
board[7][0] = ROOK
board[7][7] = ROOK

print(board)

Ahora vamos a agregar un caballo a C4:

board[4][2] = KNIGHT

print(board)

Finalmente, intenta agregar un peón en E5.