¿Qué tipos de variables básicas están disponibles y qué podemos hacer con ellas?
¿Cómo organizar el código en funciones y estructuras de control de flujo?
¿De qué estructuras de datos dispone Python?
int x = 5 # Error!
x = 5
x = "test" # Podemos cambiar el tipo de x
type(x) # <class 'str'>
numero pi = 3.1415 # Error!
numero_pi = 3.1415
1numero = 5 # Error!
numero1 = 5
SPEED_OF_LIGHT = 299_792_458 # Constante
x, y, z = 5, 3, 2
print((x + y) * z / 4) # 4.0 type(int/int) = float
print(x // y) # 1 type(int // int) = int
print(x % y) # 2
print(x ** y) # 125
print(pow(1j, 2)) # (-1+0j)
x = 5
x += 1 # x ahora es 6
y = 10**4 # 10000
x = "Matemáticas " # Comillas simples
y = 'USC' # Comillas dobles
# Si queremos poner comillas dentro de un string, podemos usar el otro tipo
quotes_str = 'se nos acabó el "chollo"'
# Comillas triples para strings multilínea
z = """wow I really love
studying here at the
USC"""
Podemos acceder a subcadenas (y a los elementos de muchas otras estructuras de datos) de una string con el operador []. Los índices de strings (y de arrays, listas, ...) están en el rango $[0, len(s)-1]$ (Python >> MATLAB)
x = "Hola"
print(x[0]) # H
print(x[1]) # o
print(x[0], x[1], x[2], x[3]) # H o l a
También podemos usar [:] para especificar un rango de índices
print(x[1:3]) # ol
print(x[:2]) # Ho
print(x[2:]) # la
El slicing en Python es muy flexible, podemos usar índices negativos que empiezan a contar desde el final de la string:
x = "índices negativos"
print(x[-1]) # s (último carácter)
print(x[-2:]) # os (desde el penúltimo hasta el final)
print(x[1:-1]) # ndices negativo (desde el segundo hasta el penúltimo)
La librería estándar de Python provee muchos métodos útiles para trabajar con strings:
Esta imagen ni siquiera está completa, por lo que solo veremos algunos de los métodos más útiles, por supuesto la referencia completa está en: docs.python.org
Este es un ejemplo de una de las características por las que Python es más apreciado: los nombres de las funciones son intuitivos y se pueden deducir comportamiento de la función..
ada = "ada lovelace"
# Métodos para cambiar capitalización
print(ada.capitalize()) # Ada lovelace
print(ada.upper()) # ADA LOVELACE
print(ada.title()) # Ada Lovelace
print("C++".lower()) # c++
# Métodos para buscar subcadenas
print(ada.startswith("ada")) # True
print(ada.endswith("lace")) # True
# Para encontrar el primer índice de una subcadena dentro de otra, usamos find
print(ada.find("love")) # 4
# Si no se encuentra, find devuelve -1
print(ada.find("python")) # -1
# Métodos para reemplazar subcadenas
print(ada.replace("lovelace", "hopper")) # ada hopper
print(ada.replace("a", "A")) # AdA lovelAce
# ...y también para eliminar espacios al principio/final
padded = " turbo padded string "
print(padded.strip()) # turbo padded string
print(padded.lstrip()) # turbo padded string
print(padded.rstrip()) # turbo padded string
# Métodos para dividir y unir strings
print(ada.split()) # ["ada", "lovelace"] <-- convierte la string a una lista, estructura que veremos más adelante
print(" ".join(["ada", "lovelace"])) # ada lovelace
# .join() es un método muy interesante, veremos más adelante otros ejemplos como el siguiente:
print(", ".join([str(i) for i in range(10)])) # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
# Métodos para comprobar si una string es de cierto tipo
print("123".isdigit()) # True
print("abc".isalpha()) # True
print("😶🌫️".isalnum()) # False
print("ABC".islower()) # False
Los métodos se pueden encadenar y se ejecutan en el orden en el que se escriben, por ejemplo:
print(" hola ".strip().capitalize()) # Hola
print("instagram\nreels") # instagram
# reels
print("value:\t10") # value: 10
print("hello\"world\"") # hello "world"
print("C:\\Users\\pablo") # C:\Users\pablo
Se pueden usar carácteres de todo tipo en strings!
epic_string = "🐉 传说中的龙在烈焰中飞翔,守护着远古的宝藏 🔥✨"
print(epic_string)
+
y *
con strings:
print("Hola" + " mundo") # Hola mundo
print("Hola" * 3) # HolaHolaHola
x = "Hola"
x[0] = "h" # Error!
# Cuando "modificamos" una variable con una string,
# solo estamos copiandola y reasignandola a una nueva string
x = x + " mundo"
x, y, cheese = 2, 3, "we ❤️ cheese"
print(f"La suma de {x} y {y} es {x + y}")
print(f"La longitud de la string es {len(cheese)}")
print(f"El número pi con 3 decimales es {3.141592653589793:.3f}") # 3.142 (usa redondeo)
print(f"La constante de gravitación universal es {6.67430e-11:.2e}") # 6.67e-11
print(f"Hexadecimal: {255:x}, Octal: {255:o}, Binario: {255:b}") # ff, 377, 11111111
# Alinear texto: útil para imprimir tablas
print(f"{'Álbum':<20} {'Año':<10} {'Género':<15}") # Álbum Año Género
print(f"{'OK Computer':<20} {'1997':<10} {'Alternative Rock':<15}") # OK Computer 1997 Alternative Rock
print(f"{'Kid A':<20} {'2000':<10} {'Art Rock':<15}") # Kid A 2000 Art Rock
print(f"{'In Rainbows':<20} {'2007':<10} {'Alternative Rock':<15}") # In Rainbows 2007 Alternative Rock
Los booleanos son un tipo de datos que solo puede tener dos valores: True o False
Se usan principalmente en estructuras de control de flujo y en comparaciones
Los booleanos son un tipo de datos que solo puede tener dos valores: True o False
Se usan principalmente en estructuras de control de flujo y en comparaciones
Por supuesto, podemos comparar strings y otros tipos de datos
Para negar un booleano, usamos not
# Operadores lógicos
print(3.14 != 3.1415) # True
print(not True) # False
print(0 < 1 and 1 < 2) # True
print(0 < 1 < 2) # True
# Comparaciones con strings
print("hola" == "hola") # True
print("hola" == "adiós") # False
print("hola" > "adiós") # True (orden alfabético)
# Hay algunos valores especiales que se pueden interpretar como Verdadero/Falso
print(True == 1) # True
print(False == 0) # True
print(bool("")) # False
print(bool("hola")) # True
Las listas son una de las estructuras más simples y flexibles del lenguaje, y actúan de forma similar a los arrays de otros lenguajes: lista = [1, "python", [1,3]]
# Crear una lista
lista = [1, 1, 2, 3]
# Añadir elementos
lista.append(5)
# Acceder a elementos, mismas reglas que con strings
print(lista[0]) # 1
print(lista[-1]) # 5
# Slicing
print(lista[1:3]) # [1, 2]
Se pueden añadir elementos con .append() y .insert()
# Append añade un elemento al final
lista = ["mira", "wassap"]
lista.append("bro") # ["mira", "wassap", "bro"]
# Insert se usa para añadir un elemento en una posición concreta
lista.insert(1, "ahora") # ["mira", "ahora", "wassap", "bro"]
Y borrar con del y .pop()
lista = ["audi", "bmw", "mercedes"]
del lista[1]
print(lista) # ["audi", "mercedes"]
Se pueden inicializar de muchas formas:
lista = list(1, 2, 3) # [1, 2, 3]
lista = list(range(10)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
lista = list("hola") # ['h', 'o', 'l', 'a']
lista = [0] * 10 # [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Y podemos usar los condicionales in y not in:
frutas = ["manzana", "banana", "cereza", "uva"]
if "banana" in frutas:
print("Genial! La banana está en la lista de frutas.")
if "kiwi" not in frutas:
print("Cáspita! El kiwi no está en la lista de frutas.")
Por supuesto, podemos ordenar los elementos:
lista = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
lista.sort()
print(lista) # [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]
sms = ["USC Notas", "Lenguaje matemático", "4.9", "Suspenso"]
sms.sort()
print(sms) # ['4.9', 'Lenguaje matemático', 'Suspenso', 'USC Notas'] (orden alfanumérico)
# Pero cuidado con ordenar listas heterogéneas!
sms = ["USC Notas", "Lenguaje matemático", 4.9, "Suspenso"]
sms.sort() # Error!
Y también podemos hacer otras operaciones como invertir el orden:
lista = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
lista.reverse()
print(lista) # [5, 3, 5, 6, 2, 9, 5, 1, 4, 1, 3]
Las tuplas son una estructura curiosa, se comportan de forma similar a las listas pero son inmutables: tupla = (1, "python", [1,3])
tupla = (1, 1, 2, 3)
print(tupla[0])
print(tupla[-1])
# No se pueden modificar elementos!
tupla[0] = 0 # Error!
# Assignments múltiples (todo esto son tuplas, se podrían escribir con paréntesis)
x, y = 1, 2
x, y = y, x
print(x, y) # 2 1
Implementa conjuntos de elementos no repetidos sin ordenar (o sea, un conjunto $X$ como los de toda la vida)
La sintaxis para declararlos es conj = {'a', 1, 'b'}
primes = {2, 3, 5, 7, 11}
odds = {1, 3, 5, 7, 9, 11}
print(primes | odds) # {1, 2, 3, 5, 7, 9, 11}
print(primes & odds) # {3, 5, 7, 11}
print(primes - odds) # {2}
print(primes ^ odds) # {1, 2, 9}
Un diccionario $d$ implementa una aplicación (mutable) entre un conjunto de keys $K$ y uno de valores $V$,
$d: K \to V$.
Son mutables, ordenados y no permiten tener varios valores para una misma key
# Crear un diccionario
datos = {"nombre": "Evariste", "apellido": "Galois", "edad": 20}
# Acceder a elementos
print(datos["nombre"]) # Pablo
# Añadir y modificar elementos es muy sencillo
datos["edad"] = 22
datos["email"] = "[email protected]"
# Podemos eliminar con del al igual que en listas
del datos["email"]
# O eliminar todo el diccionario con .clear() (esto también funciona para listas y demás)
datos.clear()
Es muy común usar diccionarios junto a listas para representar listas de información estructurada:
# Lista de estudiantes con sus datos
estudiantes = [
{"nombre": "Pablo", "apellido": "Diaz", "edad": 23},
{"nombre": "Evariste", "apellido": "Galois", "edad": 20},
{"nombre": "Ada", "apellido": "Byron", "edad": 30}
]
# Podemos indexar la lista y el diccionario a la vez
print(estudiantes[0]["nombre"]) # Pablo
O usar diccionarios encadenados para representar estructuras más complejas (siguiendo la misma sintaxis que el formato JSON):
# Estructura de información más complicada
lenguajes = {
"C++": {"creador": "Bjarne Stroustrup", "año": 1985, "caracteristicas": ["rápido", "complicado"]},
"Python": {"creador": "Guido van Rossum", "año": 1991, "caracteristicas": ["fácil", "versátil"]},
"Rust": {"creador": "Graydon Hoare", "año": 2010, "caracteristicas": ["seguro", "rápido"]}
}
Nota: en la siguiente clase veremos una forma más adecuada de representar datos estructurados, aunque esta representación es muy útil al leer o escribir ficheros
# Listas
lista = [1, 2, 3, 4, 5]
print(3 in lista) # True
print(6 not in lista) # True
# Sets
conjunto = {1, 2, 3, 4, 5}
print(3 in conjunto) # True
# Diccionarios
datos = {"nombre": "Evariste", "apellido": "Galois", "edad": 20}
print("nombre" in datos) # True
Los condicionales en Python siguen la estructura if ... elif ... else
tiempo = "lluvia"
if tiempo == "lluvia":
print("No sé si ir a Supertopo")
elif tiempo == "sol":
print("Voy a clase")
elif tiempo == "tormenta":
print("Va a ir a Supertopo su padre")
else:
print("No sé qué tiempo hace")
Los condicionales en Python siguen la estructura if ... elif ... else
tiempo = "sol"
if tiempo == "lluvia":
print("No sé si ir a Supertopo")
elif tiempo == "sol":
print("Voy a clase")
elif tiempo == "tormenta":
print("Va a ir a Supertopo su padre")
else:
print("No sé qué tiempo hace")
Los condicionales en Python siguen la estructura if ... elif ... else
tiempo = "tormenta"
if tiempo == "lluvia":
print("No sé si ir a Supertopo")
elif tiempo == "sol":
print("Voy a clase")
elif tiempo == "tormenta":
print("Va a ir a Supertopo su padre")
else:
print("No sé qué tiempo hace")
Los condicionales en Python siguen la estructura if ... elif ... else
tiempo = "tornado"
if tiempo == "lluvia":
print("No sé si ir a Supertopo")
elif tiempo == "sol":
print("Voy a clase")
elif tiempo == "tormenta":
print("Va a ir a Supertopo su padre")
else:
print("No sé qué tiempo hace")
# Sintaxis: valor_si_cierto if condición else valor_si_falso
edad = 20
print("Puedes beber" if edad >= 18 else "No puedes beber")
n = 2903
print("par" if n % 2 == 0 else "impar")
Una aclaración importante: = es para asignar un valor a una variable, mientras que == es para hacer comparaciones!
En Python, la indentación es obligatoria y se usa para delimitar bloques de código.
if x == 1:
print("x es 1") # Error de indentación
Puede parecer una tontería pero el programa no compila si no pones las tabulaciones bien
Si esto es buena decisión de diseño o son mejores los curly braces { } es un debate milenario
Por supuesto tiene que haber alguna forma de indicar jerarquía entre bloques de códigos una vez introduces condicionales, para evitar ambigüedad (problema del dangling else)
if x > 0:
if y > 0:
print("both positive")
else:
print("at least one non-positive") # de cuál if es este else?
# Bucles sobre una lista
frutas = ["manzana", "platano", "naranja", "limón", "kiwi"]
for fruta in frutas:
if fruta == "platano":
continue
print(fruta)
if fruta == "limón":
break
# Bucles con range
for i in range(5):
print(i)
for i in range(1, 11, 2):
print(i)
Hay 2 formas de iterar sobre listas, depende de si necesitamos los índices o no:
cats = ["sebastian", "supreme cat", "frozone"]
for cat in cats:
print(f"{cat.title()} es mi gato favorito")
# Si necesitamos los índices de la lista, usamos enumerate()
for i, cat in enumerate(cats):
print(f"{cat.title()} es el gato número {i+1}")
También podemos iterar sobre otras estructuras de datos
# Sobre diccionarios
datos = {"nombre": "Evariste", "apellido": "Galois", "edad": 20}
for key, value in datos.items():
print(f"{key}: {value}")
for key in datos.keys():
print(key)
for value in datos.values():
print(value)
# Sobre sets
primes = {2, 3, 5, 7, 11}
for i, p in enumerate(primes):
print(p, "es el primero número #", i)
Los bucles while se ejecutan mientras una condición sea verdadera
# Bucle infinito
while True:
pass # La palabra "pass" se usa para indicar no hacer nada, pero manteniendo la indentación de Python
# Bucle con condición
x = 0
while x < 10:
print(x)
x += 1
estudiante = {"nombre": "Lucía", "edad": 21, "carrera": "Matemáticas", "promedio": 8.75}
# IMPRIMIR COMO: Lucía tiene 21 años, estudia Matemáticas y tiene un promedio de 8.75.
A = [[1, 2], [3, 4]]
B = [[5, 6], [7, 8]]
# Deberías obtener [[19, 22], [43, 50]]