Variables y tipos de datos
"Naming things is one of the two hard problems in computer science." — Phil Karlton.
Qué vas a aprender en este capítulo
Hasta ahora tus programas son letreros: imprimís cosas y se acabó. En este capítulo aprendés a guardar datos para usarlos después y a leer datos que escriba el usuario. Vas a entender qué es una variable, qué tipos básicos existen en Python, y por qué confundir un "5" con un 5 te puede costar la primera tarde de tu primer proyecto.
3.1 La idea: una caja con un nombre
💡 Intuición
Imaginate que estás vendiendo pupusas. Cada vez que te preguntan "¿cuánto cuesta una de queso?" tenés que pensar el precio o ver la pizarra. Si decidís cambiar el precio, tenés que cambiarlo en cada cabeza, en cada pizarra, en cada cuaderno donde lo escribiste.
Una variable es una cajita con un nombre, donde guardás un valor que podés mirar (o cambiar) cuando lo necesités. En vez de escribir el número veinte veces en tu programa, escribís una vez:
precio_queso = 0.50
Y de ahí en adelante, cuando necesités el precio, usás el nombre precio_queso. Si mañana sube el precio a , cambiás una sola línea y todo el resto del programa se ajusta solo. Eso es el primer superpoder de la programación: decir las cosas una sola vez.
Una variable tiene tres partes: un nombre (cómo la llamás), un valor (qué guarda) y un tipo (de qué clase es ese valor).
📜 Historia
La palabra "variable" viene del álgebra: , , son cantidades que pueden tomar distintos valores. En programación la idea es similar pero con un giro importante: la variable de un programa cambia con el tiempo. En matemáticas, es lo que sea pero es una sola cosa fija dentro de la ecuación. En programación, x puede valer 5 ahora y 12 dos líneas después.
Los primeros lenguajes (FORTRAN, 1957) heredaron el nombre del álgebra. Pero cuidado: cuando alguien con formación matemática lee x = x + 1 se vuelve loco — "¡cero igual a uno!". El = de programación no es igualdad, es asignación ("guardá esto en aquella caja"). Hay lenguajes que lo escriben distinto (x := x + 1 en Pascal, (set! x (+ x 1)) en Scheme) precisamente para evitar la confusión.
3.2 Asignación
📐 Fundamento
La sintaxis básica es:
nombre = valor
A la izquierda del =, el nombre de la variable. A la derecha, una expresión que se evalúa primero y cuyo resultado se guarda. Lo de "se evalúa primero" es clave: la asignación calcula el lado derecho y luego lo deposita.
edad = 19
precio_queso = 0.50
nombre = "Maria"
ciclo = 1 + 0 # Python primero suma, luego asigna 1 a ciclo
Reasignación. Una variable puede cambiar de valor:
contador = 0
contador = contador + 1 # ahora vale 1
contador = contador + 1 # ahora vale 2
La línea contador = contador + 1 se lee así: "calculá contador + 1 con el valor actual de contador, y guardá el resultado de nuevo en contador". Por eso no es un absurdo matemático.
Múltiple asignación. Python permite asignar varias variables de una sola vez:
x, y, z = 1, 2, 3
nombre, edad = "Carlos", 20
Útil cuando una función devuelve varios valores; lo vamos a usar más adelante.
⚠️ Trampa común
x = 5 no es lo mismo que 5 = x. El nombre va siempre a la izquierda. Si invertís el orden, Python protesta:
5 = x
# SyntaxError: cannot assign to literal here. ...
Esa es una protección — 5 no es una caja, es un valor; no podés meter algo dentro de un literal.
== no es lo mismo que =. El de un solo signo asigna; el de dos compara. Lo vemos en el capítulo de condicionales, pero ya conviene tener el ojo entrenado.
3.3 Reglas para nombrar variables
📐 Fundamento
Reglas obligatorias (si no las seguís, Python da error):
- Empiezan con letra (a–z, A–Z) o guión bajo (
_). Nunca con número. - Solo letras, números y guión bajo. Sin espacios, sin
-, sin?, sin tildes ni eñes. - Distinguen mayúsculas de minúsculas:
precio≠Precio≠PRECIO. - No pueden ser una palabra reservada del lenguaje (
if,for,def,class,True,None, etc.).
Convenciones del estilo PEP 8 (no obligatorias, pero todo el mundo Python las sigue):
snake_casepara variables y funciones. Palabras separadas por guión bajo, todo en minúsculas:precio_total,nombre_completo,cantidad_pupusas.MAYUSCULAS_CON_GUIONpara constantes (valores que no cambian):PI = 3.14159,IVA = 0.13.- Nombres descriptivos.
precio_unitarioes mejor quepu. La memoria de la computadora es barata; tu memoria, no. - Sin tildes ni eñes.
añotécnicamente funciona en Python 3, pero por convención del proyecto y portabilidad, usáaniooyear.
Tabla de palabras reservadas (Python 3, no las podés usar como nombres):
False None True and as assert async
await break class continue def del elif
else except finally for from global if
import in is lambda nonlocal not or
pass raise return try while with yield
No las memorices; tu editor te las marca con color y te avisa si chocás con una.
3.4 Los tipos básicos
📐 Fundamento
Cada valor en Python tiene un tipo: una etiqueta que dice de qué clase es ese valor. Los cuatro tipos básicos que vas a usar todo el tiempo:
| Tipo | Nombre Python | Ejemplos | Para qué sirve |
|---|---|---|---|
| Entero | int |
0, 42, -7, 1000000 |
Contar cosas, indexar |
| Decimal | float |
0.5, 3.14, -2.7, 1e6 |
Medir, calcular precios |
| Texto | str |
"Hola", 'Maria', "" |
Nombres, mensajes, identificadores |
| Booleano | bool |
True, False |
Sí/no, verdadero/falso |
int (enteros). Números sin parte decimal. En Python 3, los enteros son arbitrariamente grandes — podés tener un número con 500 dígitos sin romper nada. Esa es una diferencia bonita con C o Java, donde un entero típico se rompe pasando los 2 mil millones.
float (punto flotante). Números con parte decimal. Internamente se guardan en formato IEEE 754 de 64 bits. Esa representación tiene precisión finita, lo que produce sorpresas:
>>> 0.1 + 0.2
0.30000000000000004
Eso no es un bug, es la realidad: no se puede representar exactamente en binario, igual que no se puede representar exactamente en decimal (). Para dinero crítico (bancos, contabilidad) se usa el módulo decimal o se trabaja en centavos como entero. Para casi todo lo demás, float está bien.
str (cadenas de texto). Secuencia de caracteres. En Python, un solo carácter ya es un str de longitud 1; no hay tipo char aparte. Las cadenas se delimitan con comillas:
nombre = "Maria" # comillas dobles
saludo = 'Hola' # comillas simples (equivalentes)
parrafo = """Una
cadena que
ocupa varias
lineas""" # triples para multilínea
Las dobles y simples son intercambiables. Usá las que te dejen escribir tu texto sin escapar: si tu cadena contiene ', envolvela en ", y viceversa.
bool (booleanos). Solo dos valores: True y False. Notá las mayúsculas: true (minúsculas) no funciona en Python. El nombre viene de George Boole, matemático del siglo XIX que formalizó la lógica con álgebra. Los booleanos son el corazón de las decisiones — los vemos a fondo en el capítulo de condicionales.
Curiosidad útil: bool en Python es técnicamente una subclase de int. True vale 1 y False vale 0. Por eso podés sumar booleanos:
>>> True + True + False
2
Útil para contar cuántas condiciones se cumplen sin escribir un if por cada una.
Cómo preguntar el tipo de un valor
>>> type(42)
<class 'int'>
>>> type(3.14)
<class 'float'>
>>> type("Hola")
<class 'str'>
>>> type(True)
<class 'bool'>
type(...) te devuelve la clase de un valor. Útil cuando algo no funciona y querés diagnosticar qué guardó la variable realmente.
3.5 Tipado dinámico
📐 Fundamento
Python es de tipado dinámico: la misma variable puede guardar valores de tipos distintos a lo largo del programa.
x = 10 # ahora x es int
x = "diez" # ahora x es str
x = 10.0 # ahora x es float
Eso es legal y funciona. No hagas eso a propósito. Aunque el lenguaje lo permite, cambiar el tipo de una variable según la línea hace tu programa imposible de leer. Convención sana: una variable lleva un tipo durante toda su vida.
Comparación con tipado estático. En lenguajes como Java o C++, declarás el tipo al crear la variable y no se puede cambiar:
int x = 10;
x = "diez"; // ERROR de compilación: incompatible types
Esa restricción atrapa errores antes de ejecutar el programa, pero requiere más escritura. Python eligió el otro lado: menos verbosidad, más libertad — y más cuidado del programador.
Type hints (anuncio). Python moderno permite anotar tipos para que herramientas como mypy los verifiquen, sin perder la flexibilidad dinámica:
edad: int = 19
nombre: str = "Maria"
Por ahora no los necesitás. Los retomamos en el capítulo de funciones.
3.6 Hablar con el usuario: input y conversiones
📐 Fundamento
Los programas dejan de ser letreros cuando reciben datos del usuario. La función para eso es input:
nombre = input("Cómo te llamás? ")
print("Hola,", nombre)
Cuando Python ejecuta input(...), pausa la ejecución, muestra el mensaje (el "prompt"), y espera a que el usuario escriba algo y pulse Enter. Lo que el usuario haya escrito se devuelve como una cadena (str).
Importantísimo: input siempre devuelve un str. Aunque el usuario escriba dígitos.
edad = input("Edad: ") # el usuario escribe 19
print(edad + 1) # ERROR: can only concatenate str to str
El usuario tipeó "19", pero eso es la cadena "19", no el entero 19. Sumarle un número es como pedirle "lunes" + "1": no tiene sentido.
Conversiones explícitas. Cuando necesités tratar la entrada como número, convertí:
| Conversión | Función |
|---|---|
| Cadena → entero | int("19") → 19 |
| Cadena → flotante | float("3.14") → 3.14 |
| Número → cadena | str(19) → "19" |
| Cadena → booleano | (más sutil — se ve abajo) |
Versión correcta:
edad = int(input("Edad: "))
print(edad + 1, "años el próximo cumpleaños.")
Conversión que falla. Si el usuario escribe basura, int(...) revienta:
>>> int("hola")
ValueError: invalid literal for int() with base 10: 'hola'
En el capítulo de condicionales aprendemos a defendernos de eso. Por ahora, asumí que el usuario coopera.
bool con cadenas — trampa. Toda cadena no vacía da True cuando se convierte a bool. Solo "" (cadena vacía) da False:
>>> bool("False") # ¡cuidado!
True
>>> bool("")
False
Si querés leer un sí/no del usuario, no convirtás directo a bool. Compará: respuesta == "si".
⚠️ Trampa común
Olvidar la conversión. El error #1 de los principiantes con input:
a = input("Primer numero: ") # str
b = input("Segundo numero: ") # str
suma = a + b # CONCATENACIÓN, no suma
print(suma)
Si el usuario escribe 3 y 4, el programa imprime 34, no 7. Python no sumó: pegó las cadenas. Arreglo:
a = int(input("Primer numero: "))
b = int(input("Segundo numero: "))
suma = a + b
print(suma)
Convertir antes de validar. Si convertís sin saber qué te dieron, el programa puede explotar:
edad = int(input("Edad: ")) # si el usuario escribe "diecinueve", boom
Por ahora aceptamos la explosión (es una forma cruda de feedback). Más adelante con try/except lo manejamos elegante.
3.7 La función print con f-strings
Ya conocés print(a, b, c). Cuando querés mensajes más cuidados, usá f-strings (cadenas formateadas, disponibles desde Python 3.6):
nombre = "Carlos"
edad = 20
print(f"Hola, {nombre}, tenés {edad} años.")
La f antes de la comilla activa la magia. Dentro de la cadena, lo que pongas entre { } se evalúa como expresión Python y se inserta en el lugar.
precio = 0.50
cantidad = 3
print(f"{cantidad} pupusas a <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>p</mi><mi>r</mi><mi>e</mi><mi>c</mi><mi>i</mi><mi>o</mi><mo>:</mo><mn>.2</mn><mi>f</mi></mrow><mi>c</mi><mi>a</mi><mi>d</mi><mi>a</mi><mi>u</mi><mi>n</mi><mi>a</mi><mo>=</mo></mrow><annotation encoding="application/x-tex">{precio:.2f} cada una = </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mord mathnormal" style="margin-right:0.0278em;">r</span><span class="mord mathnormal">ec</span><span class="mord mathnormal">i</span><span class="mord mathnormal">o</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">.2</span><span class="mord mathnormal" style="margin-right:0.1076em;">f</span></span><span class="mord mathnormal">c</span><span class="mord mathnormal">a</span><span class="mord mathnormal">d</span><span class="mord mathnormal">a</span><span class="mord mathnormal">u</span><span class="mord mathnormal">na</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span></span></span></span>{precio * cantidad:.2f}")
Salida:
3 pupusas a <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0.50</mn><mi>c</mi><mi>a</mi><mi>d</mi><mi>a</mi><mi>u</mi><mi>n</mi><mi>a</mi><mo>=</mo></mrow><annotation encoding="application/x-tex">0.50 cada una = </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">0.50</span><span class="mord mathnormal">c</span><span class="mord mathnormal">a</span><span class="mord mathnormal">d</span><span class="mord mathnormal">a</span><span class="mord mathnormal">u</span><span class="mord mathnormal">na</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span></span></span></span>1.50
El :.2f es un formato: "número con 2 decimales". Algunos formatos útiles:
| Formato | Resultado | Uso |
|---|---|---|
{precio:.2f} |
0.50 |
Dinero, dos decimales |
{cantidad:,} |
1,000,000 |
Separador de miles |
{nombre:>10} |
" Carlos" |
Alinear a la derecha en 10 columnas |
{nombre:<10} |
"Carlos " |
Alinear a la izquierda |
{ratio:.1%} |
34.5% |
Porcentaje |
Vamos a ver más en el capítulo de operadores y expresiones. Por ahora :.2f te alcanza para precios.
3.8 Operaciones con cadenas
Aunque las operaciones aritméticas serias las vemos en el próximo capítulo, conviene mostrar lo básico de cadenas:
# Concatenación con +
saludo = "Hola, " + "mundo" # "Hola, mundo"
# Repetición con *
linea = "=" * 30 # "=============================="
# Longitud con len
n = len("Maria") # 5
# Mayúsculas / minúsculas
"hola".upper() # "HOLA"
"HOLA".lower() # "hola"
"maria lopez".title() # "Maria Lopez"
# Eliminar espacios al inicio y al final
" con espacios ".strip() # "con espacios"
# Buscar y reemplazar
"pupusa de queso".replace("queso", "frijol") # "pupusa de frijol"
upper, lower, strip, replace se llaman métodos — funciones que viven dentro del objeto. La sintaxis es objeto.metodo(argumentos). Vamos a usar métodos a montones desde acá hasta el final del libro.
3.9 Proyecto: precios de la pupusería en variables
🏗️ Avance del proyecto — Pupusería La Esquina
En el capítulo anterior teníamos los precios pegados a las líneas de print. Ahora los factorizamos en variables, para poder calcular después. Creá pupuseria.py con esto:
# Pupuseria La Esquina - Sistema de pedidos
# Capitulo 3: precios en variables y entrada del usuario
# --- Datos de la pupuseria ---
NOMBRE_PUPUSERIA = "Pupuseria La Esquina"
CIUDAD = "San Miguel"
IVA = 0.13 # 13% en El Salvador
# --- Precios (en dolares) ---
precio_queso = 0.50
precio_revuelta = 0.60
precio_chicharron = 0.60
precio_curtido = 0.25
precio_refresco = 1.00
# --- Encabezado ---
ancho = 35
print("=" * ancho)
print(f" {NOMBRE_PUPUSERIA}")
print(f" {CIUDAD}, El Salvador")
print("=" * ancho)
print()
# --- Menu ---
print("Menu:")
print(f" 1. Pupusa de queso ........ ${precio_queso:.2f}")
print(f" 2. Pupusa revuelta ........ ${precio_revuelta:.2f}")
print(f" 3. Pupusa de chicharron ... ${precio_chicharron:.2f}")
print(f" 4. Curtido (extra) ........ ${precio_curtido:.2f}")
print(f" 5. Refresco de tamarindo .. ${precio_refresco:.2f}")
print()
# --- Pedido ---
nombre_cliente = input("Su nombre: ")
cantidad_queso = int(input("Cuantas pupusas de queso? "))
# --- Calculo (lo profundizamos en el proximo capitulo) ---
subtotal = cantidad_queso * precio_queso
impuesto = subtotal * IVA
total = subtotal + impuesto
# --- Recibo ---
print()
print("=" * ancho)
print(f" Recibo para {nombre_cliente}")
print("=" * ancho)
print(f" {cantidad_queso} x pupusa de queso ... ${subtotal:.2f}")
print(f" IVA (13%) ................ ${impuesto:.2f}")
print(f" TOTAL .................... ${total:.2f}")
print("=" * ancho)
print(f" Gracias, {nombre_cliente}!")
Mejoras logradas en este capítulo:
- Los precios viven en un solo lugar. Si cambian, cambiás una línea.
- El programa ya interactúa — pregunta el nombre y la cantidad.
- Hace una cuenta real con IVA.
Lo que falta (para los próximos capítulos):
- Que pueda elegir entre varios tipos de pupusa (capítulo 5 — condicionales).
- Que pueda pedir varias rondas (capítulo 6 — bucles).
- Reutilizar el cálculo en una función (capítulo 7 — funciones).
3.10 Resumen visual
| Concepto | Una línea para recordar |
|---|---|
| Variable | Caja con nombre que guarda un valor. |
= |
Asignación: "guardá esto en aquella caja". |
int |
Entero (sin parte decimal): 42, -7. |
float |
Decimal: 0.5, 3.14. |
str |
Texto: "Hola", 'Maria'. |
bool |
Verdadero/falso: True, False. |
type(x) |
Te dice de qué tipo es el valor. |
input(prompt) |
Lee del teclado. Siempre devuelve str. |
int(...), float(...), str(...) |
Convierten entre tipos. |
| f-string | f"texto {variable}" — formato moderno y limpio. |
3.11 Ejercicios
✏️ Ejercicio 3.1 — Promedio de tres notas
Escribí un programa promedio.py que pida tres notas (números entre 0 y 10) y muestre el promedio con dos decimales.
Solución
n1 = float(input("Nota 1: "))
n2 = float(input("Nota 2: "))
n3 = float(input("Nota 3: "))
promedio = (n1 + n2 + n3) / 3
print(f"Promedio: {promedio:.2f}")
Detalles: usamos float (no int) porque las notas pueden tener decimales (8.5). Los paréntesis alrededor de la suma son obligatorios — sin ellos, Python divide solo n3 / 3 por la regla de precedencia.
✏️ Ejercicio 3.2 — Conversor de minutos a horas
Pedile al usuario un número de minutos y mostrale cuántas horas y minutos son. Por ejemplo, 135 minutos → "2 horas y 15 minutos".
Solución
minutos_total = int(input("Minutos: "))
horas = minutos_total // 60 # division entera
minutos = minutos_total % 60 # resto
print(f"{horas} horas y {minutos} minutos")
// es división entera (descarta el resto) y % es el resto (módulo). Los vemos a fondo en el próximo capítulo.
✏️ Ejercicio 3.3 — Datos personales
Pedile al usuario nombre, edad y altura en metros. Mostrale un mensaje formateado del tipo:
Hola, Maria! Tenes 19 años y 1.65 metros de altura.
El año en que naciste fue 2007.
(Asumí que estamos en 2026.)
Solución
ANIO_ACTUAL = 2026
nombre = input("Nombre: ")
edad = int(input("Edad: "))
altura = float(input("Altura (m): "))
anio_nacimiento = ANIO_ACTUAL - edad
print(f"Hola, {nombre}! Tenes {edad} años y {altura} metros de altura.")
print(f"El año en que naciste fue {anio_nacimiento}.")
✏️ Ejercicio 3.4 — Diagnóstico de tipos
Sin ejecutar, decí qué imprime cada línea. Si pensás que da error, decí cuál.
a = "5"
b = 5
c = 5.0
d = True
print(type(a))
print(type(b))
print(type(c))
print(type(d))
print(a + a)
print(b + b)
print(b + c)
print(b + d)
print(a + b)
Solución
<class 'str'>
<class 'int'>
<class 'float'>
<class 'bool'>
55 # str + str = concatenación
10 # int + int = 10
10.0 # int + float = float
6 # int + bool: True vale 1, así que 5 + 1
TypeError # str + int: incompatibles
Las primeras 8 funcionan. La novena (a + b, str + int) revienta con TypeError: can only concatenate str (not "int") to str. Para concatenar tendrías que escribir a + str(b), o mejor, usar f-string: f"{a}{b}".
✏️ Ejercicio 3.5 — Pupusería con dos productos
Modificá el programa de la pupusería para que pregunte la cantidad de pupusas de queso y la cantidad de pupusas revueltas. Calculá el subtotal, el IVA y el total. Mostrá un recibo.
Solución
precio_queso = 0.50
precio_revuelta = 0.60
IVA = 0.13
cant_q = int(input("Pupusas de queso: "))
cant_r = int(input("Pupusas revueltas: "))
subtotal = cant_q * precio_queso + cant_r * precio_revuelta
impuesto = subtotal * IVA
total = subtotal + impuesto
print()
print("====== RECIBO ======")
print(f"Queso x {cant_q} ........ ${cant_q * precio_queso:.2f}")
print(f"Revuelta x {cant_r} ..... ${cant_r * precio_revuelta:.2f}")
print(f"Subtotal ............ ${subtotal:.2f}")
print(f"IVA (13%) ........... ${impuesto:.2f}")
print(f"TOTAL ............... ${total:.2f}")
3.12 Para profundizar
- PEP 8 — Style Guide for Python Code: https://peps.python.org/pep-0008/. La parte de naming conventions es la más útil ahora.
- Documentación oficial sobre tipos: https://docs.python.org/es/3/library/stdtypes.html. Lectura para curiosos.
- Lectura recomendada: "What Every Computer Scientist Should Know About Floating-Point Arithmetic" de David Goldberg. Si alguna vez te muerde la representación de los
float, este paper lo explica de raíz. - Próximo capítulo: Operadores y expresiones — todo lo que se puede hacer con los tipos básicos.
Definiciones nuevas: variable, asignación, tipo, int, float, str, bool, tipado dinámico, input, conversión, f-string, método.