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 0.500.50 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 0.600.60, 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: xx, yy, zz 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, xx 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):

  1. Empiezan con letra (a–z, A–Z) o guión bajo (_). Nunca con número.
  2. Solo letras, números y guión bajo. Sin espacios, sin -, sin ?, sin tildes ni eñes.
  3. Distinguen mayúsculas de minúsculas: precioPrecioPRECIO.
  4. 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_case para variables y funciones. Palabras separadas por guión bajo, todo en minúsculas: precio_total, nombre_completo, cantidad_pupusas.
  • MAYUSCULAS_CON_GUION para constantes (valores que no cambian): PI = 3.14159, IVA = 0.13.
  • Nombres descriptivos. precio_unitario es mejor que pu. La memoria de la computadora es barata; tu memoria, no.
  • Sin tildes ni eñes. año técnicamente funciona en Python 3, pero por convención del proyecto y portabilidad, usá anio o year.

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: 0.10.1 no se puede representar exactamente en binario, igual que 1/31/3 no se puede representar exactamente en decimal (0.3330.333\ldots). 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:

  1. Los precios viven en un solo lugar. Si cambian, cambiás una línea.
  2. El programa ya interactúa — pregunta el nombre y la cantidad.
  3. 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.

✏️ 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".

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

✏️ 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)

✏️ 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.

3.12 Para profundizar


Definiciones nuevas: variable, asignación, tipo, int, float, str, bool, tipado dinámico, input, conversión, f-string, método.