Este es el curso intensivo que me hubiera gustado tener: lo que realmente vas a usar, los errores que realmente vas a encontrar, y permiso para saltarte el resto por ahora. Léelo, o dale ▶ Escuchar en cualquier sección y aprende mientras preparas el café.
🎙️ Publicado y grabado:
Nombre a la izquierda, valor a la derecha, listo. Sin declaraciones de tipo, sin punto y coma. Los type hints también déjalos para después — los verás más adelante y tendrán sentido entonces.
name = "Ada" # string
age = 36 # integer
height = 1.7 # float
is_ready = True # T mayúscula — true en minúscula crashea
nothing = None # el "null" de Python, con N mayúscula
print(name, age) # Ada 36
NameError: name 'true' is not definedTrue/False, no true/false. Si vienes de JavaScript, vas a escribir la versión en minúscula al menos tres veces esta semana.
Python tiene tres formas de formatear strings. Ignora dos. El formato con % y .format() existen en tutoriales antiguos y código legacy — solo necesitas escribir f-strings: una f antes de la comilla, variables entre llaves.
name = "Ada"
msgs = 5
print(f"Hi {name}, you have {msgs} messages")
# los cuatro métodos que cubren el 90% del trabajo real con strings:
s = " Swift Grasp "
s.strip() # "Swift Grasp" — quita espacios
s.lower() # para comparaciones sin importar mayúsculas
s.split() # ['Swift', 'Grasp']
", ".join(["a", "b"]) # "a, b" — sí, join vive en el separador
TypeError: can only concatenate str (not "int") to str"age: " + 36. Python se niega a pegar texto con números. No pongas str() por todos lados — usa un f-string: f"age: {36}" y el problema no vuelve.
No hay llaves. Los dos puntos abren un bloque, y la indentación es la sintaxis. Esta es la fuente número uno de crashes el primer día, así que vamos a enfrentarlo directamente.
score = 87
if score >= 90:
print("A")
elif score >= 80:
print("B") # este se ejecuta
else:
print("keep going")
# and / or / not son palabras, no && || !
if 80 <= score < 90: # comparación encadenada — muy Python
print("solid B")
label = "pass" if score >= 60 else "fail"
IndentationError: unexpected indent o su gemelo malvado TabError: inconsistent use of tabs and spacesEl contenedor que usarás a diario: ordenado, mezclable, crece según necesites. Dos ideas cargan con la mayor parte del peso — los índices negativos cuentan desde el final, y los slices cortan rangos.
langs = ["python", "js", "rust"]
langs.append("go") # añadir al final
langs[0] # "python"
langs[-1] # "go" — último elemento, sin len()
langs[1:3] # ['js', 'rust'] — el índice final no se incluye
len(langs) # 4
"rust" in langs # True
nums = [3, 1, 2]
sorted(nums) # copia nueva ordenada: [1, 2, 3]
nums.sort() # ordena in place, devuelve None (!)
IndexError: list index out of rangelangs[4] se sale del final. Cuando quieras el último elemento, usa langs[-1] en vez de langs[len(langs)-1]; el segundo es donde nacen estos bugs.
Pares clave–valor, como un objeto JSON. Yo diría que la mitad del Python productivo es pasar diccionarios de un lado a otro, así que aprende un hábito temprano: corchetes cuando la clave debe existir, .get() cuando podría no estar.
user = {"name": "Ada", "age": 36}
user["name"] # "Ada"
user["role"] = "admin" # añadir o sobreescribir
user.get("email") # None — sin crash
user.get("email", "n/a") # "n/a" — con un valor por defecto
for key, value in user.items():
print(f"{key} = {value}")
KeyError: 'email'.get() con un valor por defecto es la versión tranquila.
El for de Python recorre los elementos directamente — si estás escribiendo for i in range(len(things)), para, siempre hay una forma más limpia. ¿Necesitas también el índice? Para eso está enumerate.
for lang in ["python", "js", "rust"]:
print(lang)
for i, lang in enumerate(["a", "b"]):
print(i, lang) # 0 a, luego 1 b
for i in range(3): # solo números: 0, 1, 2
print(i)
count = 3
while count > 0:
count -= 1 # no existe count-- en Python
for x in items[:], o construye una lista nueva con una comprensión (siguiente sección).
Se definen con def, devuelven resultados con return. Los valores por defecto hacen los argumentos opcionales, y llamar con nombres — greet(excited=True) — mantiene las llamadas legibles seis meses después.
def greet(name, excited=False):
msg = f"Hello, {name}"
return msg + "!" if excited else msg
greet("Ada") # Hello, Ada
greet("Ada", excited=True) # Hello, Ada!
# devolver dos cosas (es una tupla, se desempaqueta al llegar)
def min_max(nums):
return min(nums), max(nums)
lo, hi = min_max([3, 1, 9]) # lo=1, hi=9
def add(item, items=[]). Esa lista por defecto se crea una sola vez y se comparte entre todas las llamadas — los elementos de la primera llamada aparecen en la segunda. A todo programador Python le pasa esto exactamente una vez. Usa items=None, luego if items is None: items = [] adentro.
Construye una lista nueva en una línea: transformación a la izquierda, bucle en el medio, filtro a la derecha. Una regla honesta — si necesita más de un if o un bucle anidado, escribe un bucle normal. Las líneas ingeniosas son como pierdes una tarde entera.
nums = [1, 2, 3, 4, 5]
squares = [n * n for n in nums] # [1, 4, 9, 16, 25]
evens = [n for n in nums if n % 2 == 0] # [2, 4]
# versión con diccionario
lengths = {w: len(w) for w in ["hi", "hello"]}
# {'hi': 2, 'hello': 5}
Siempre abre archivos con with — los cierra por ti aunque el código crashee a mitad. Y siempre pasa encoding="utf-8". Los tutoriales se lo saltan porque funciona en su Mac; en Windows el encoding por defecto es diferente y los archivos reales te van a morder.
with open("notes.txt", "w", encoding="utf-8") as f:
f.write("line one\n")
with open("notes.txt", encoding="utf-8") as f:
for line in f: # línea por línea, cualquier tamaño
print(line.strip())
# JSON de entrada y salida — lo harás cada semana
import json
with open("data.json", "w", encoding="utf-8") as f:
json.dump({"name": "Ada"}, f)
UnicodeDecodeError: 'charmap' codec can't decode byte 0x9dencoding="utf-8" en Windows. La solución es el hábito de arriba; los seis caracteres de tipeo son más baratos que la hora de confusión.
Dos habilidades aquí. Primera: cuando aparece un traceback, lee la última línea primero — ese es el error real; las líneas de arriba son solo el rastro. Segunda: captura tipos de error específicos. Un except: desnudo se traga todos los bugs del bloque y pasarás horas buscando lo que se comió.
try:
age = int("not a number")
except ValueError:
print("that wasn't a number")
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"oops: {e}")
# lanza el tuyo cuando la entrada no tiene sentido
def set_age(age):
if age < 0:
raise ValueError("age can't be negative")
Traceback (most recent call last): … significa que lo leas de abajo hacia arriba. Última línea = qué salió mal. Penúltima = el archivo y línea exactos. Todo lo de arriba = cómo llegó el programa ahí. La mayoría de los principiantes leen de arriba a abajo y se pierden en las tripas del framework.
Opinión honesta: puedes escribir Python útil durante semanas sin definir una clase, así que no te atasques aquí. Aprende a leerlas — __init__ se ejecuta al crear el objeto, self es el objeto hablando de sí mismo — y sigue adelante. Cuando tus diccionarios se vuelvan inmanejables, vuelve.
class Dog:
def __init__(self, name):
self.name = name
self.tricks = []
def learn(self, trick):
self.tricks.append(trick)
return f"{self.name} learned {trick}"
rex = Dog("Rex")
rex.learn("sit")
rex.tricks # ['sit']
TypeError: learn() takes 1 positional argument but 2 were givenself en la definición del método. El primer parámetro de cada método es self — Python pasa el objeto automáticamente, así que los conteos parecen desfasados por uno hasta que esto hace clic.
Las líneas que todo el mundo busca en Google cien veces. Guarda esta sección en favoritos; para eso está.
# intercambiar dos variables
a, b = b, a
# invertir una lista o string
nums[::-1]
# eliminar duplicados manteniendo el orden (list(set(x)) desordena)
list(dict.fromkeys(items))
# elemento más común
from collections import Counter
Counter(words).most_common(1)
# fusionar dos dicts (el de la derecha gana en conflictos)
merged = {**defaults, **overrides}
# leer input del usuario
name = input("Name: ")
# instalar un paquete / ejecutar un script (en la terminal)
# pip install requests
# python script.py
Eso es el núcleo funcional del lenguaje. Lo que lo fija no es leer más — elige algo pequeño y molesto de tu vida (renombrar una carpeta de archivos, una lista de tareas en la terminal) y constrúyelo. Ya sabes lo suficiente.