{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "40b035d4",
   "metadata": {},
   "source": [
    "[Índice](README.md) · [Siguiente →](02_control_del_flujo.ipynb)\n",
    "\n",
    "# 01 · Tipos de datos y variables\n",
    "\n",
    "**Audiencia.** Personas que ya han visto algo de programación y quieren repasar Python de forma práctica.  \n",
    "**Prerrequisitos.** Saber ejecutar una celda de Jupyter; no hace falta conocer Python.  \n",
    "**Duración orientativa.** 60–90 minutos, incluida la práctica.\n",
    "\n",
    "## Objetivos de aprendizaje\n",
    "\n",
    "- Reconocer los tipos escalares principales de Python.\n",
    "- Crear variables con nombres claros y comprender la asignación.\n",
    "- Convertir valores de forma explícita y combinar operadores.\n",
    "- Trabajar con texto, valores booleanos y `None`.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92bf7539",
   "metadata": {},
   "source": [
    "## Itinerario\n",
    "\n",
    "1. Valores y tipos\n",
    "2. Variables\n",
    "3. Números y operadores\n",
    "4. Booleanos\n",
    "5. Cadenas\n",
    "6. Conversiones\n",
    "7. Práctica\n",
    "\n",
    "> **Cómo trabajar:** ejecuta las celdas en orden, predice el resultado antes de verlo y modifica los ejemplos. Cada bloque termina con un ejercicio, un punto de partida y una solución posible.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dbc1263b",
   "metadata": {},
   "source": [
    "## 1. Valores y tipos\n",
    "\n",
    "En Python cada valor tiene un **tipo**, que determina qué operaciones admite. `type()` permite inspeccionarlo. Los nombres de tipo más frecuentes al empezar son `int`, `float`, `complex`, `bool`, `str` y `NoneType`.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "6080c06b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-08-02T22:29:41.563827Z",
     "iopub.status.busy": "2026-08-02T22:29:41.563695Z",
     "iopub.status.idle": "2026-08-02T22:29:41.568667Z",
     "shell.execute_reply": "2026-08-02T22:29:41.568462Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(42, 'int'),\n",
       " (3.14, 'float'),\n",
       " ((2+3j), 'complex'),\n",
       " (True, 'bool'),\n",
       " ('Python', 'str'),\n",
       " (None, 'NoneType')]"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ejemplos = [42, 3.14, 2 + 3j, True, \"Python\", None]\n",
    "[(valor, type(valor).__name__) for valor in ejemplos]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a8ef2031",
   "metadata": {},
   "source": [
    "Python usa **tipado dinámico**: una variable no queda ligada para siempre a un tipo. El valor sí tiene tipo; el nombre simplemente apunta a ese valor. Esto ofrece flexibilidad, pero cambiar de tipo sin motivo suele dificultar la lectura.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "712a9a68",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-08-02T22:29:41.570101Z",
     "iopub.status.busy": "2026-08-02T22:29:41.569970Z",
     "iopub.status.idle": "2026-08-02T22:29:41.572272Z",
     "shell.execute_reply": "2026-08-02T22:29:41.572047Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10 int\n",
      "10.5 float\n"
     ]
    }
   ],
   "source": [
    "puntuacion = 10\n",
    "print(puntuacion, type(puntuacion).__name__)\n",
    "\n",
    "puntuacion = 10.5\n",
    "print(puntuacion, type(puntuacion).__name__)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2e01ef27",
   "metadata": {},
   "source": [
    "## 2. Variables y asignación\n",
    "\n",
    "Usa nombres descriptivos en `snake_case`. No pueden comenzar con un número ni coincidir con palabras reservadas como `if`, `for` o `class`. Por convención, las constantes se escriben en mayúsculas.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "e3c213d3",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-08-02T22:29:41.573999Z",
     "iopub.status.busy": "2026-08-02T22:29:41.573871Z",
     "iopub.status.idle": "2026-08-02T22:29:41.576477Z",
     "shell.execute_reply": "2026-08-02T22:29:41.576272Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('Ada', 36, 20, 10)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nombre_usuario = \"Ada\"\n",
    "edad = 36\n",
    "PI_APROXIMADO = 3.1416\n",
    "\n",
    "# Asignación múltiple y desempaquetado\n",
    "x, y = 10, 20\n",
    "x, y = y, x\n",
    "nombre_usuario, edad, x, y\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0715c8a3",
   "metadata": {},
   "source": [
    "La asignación `=` no significa «es igual a» en sentido matemático: vincula un nombre con un valor. `==` compara valores. Los operadores aumentados actualizan a partir del valor actual: `+=`, `-=`, `*=`, `/=`.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "a19e64e7",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-08-02T22:29:41.577769Z",
     "iopub.status.busy": "2026-08-02T22:29:41.577669Z",
     "iopub.status.idle": "2026-08-02T22:29:41.579618Z",
     "shell.execute_reply": "2026-08-02T22:29:41.579411Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Valor actualizado: 10\n",
      "¿Es igual a 10? True\n"
     ]
    }
   ],
   "source": [
    "contador = 7\n",
    "contador += 3\n",
    "print(\"Valor actualizado:\", contador)\n",
    "print(\"¿Es igual a 10?\", contador == 10)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9580a25e",
   "metadata": {},
   "source": [
    "## 3. Números y operadores\n",
    "\n",
    "- `int`: enteros de precisión arbitraria.\n",
    "- `float`: números en coma flotante; son aproximaciones binarias.\n",
    "- `complex`: números con parte real e imaginaria.\n",
    "\n",
    "Precedencia básica: paréntesis, potencias, multiplicación/división y suma/resta.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d6e46ea8",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-08-02T22:29:41.580879Z",
     "iopub.status.busy": "2026-08-02T22:29:41.580797Z",
     "iopub.status.idle": "2026-08-02T22:29:41.583270Z",
     "shell.execute_reply": "2026-08-02T22:29:41.583039Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'suma': 22,\n",
       " 'resta': 12,\n",
       " 'producto': 85,\n",
       " 'division_real': 3.4,\n",
       " 'division_entera': 3,\n",
       " 'resto': 2,\n",
       " 'potencia': 289}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a, b = 17, 5\n",
    "resultados = {\n",
    "    \"suma\": a + b,\n",
    "    \"resta\": a - b,\n",
    "    \"producto\": a * b,\n",
    "    \"division_real\": a / b,\n",
    "    \"division_entera\": a // b,\n",
    "    \"resto\": a % b,\n",
    "    \"potencia\": a ** 2,\n",
    "}\n",
    "resultados\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68015175",
   "metadata": {},
   "source": [
    "Los `float` no representan exactamente todos los decimales. Para compararlos, suele ser mejor `math.isclose()` que `==`. Para dinero real se suele usar `decimal.Decimal`.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "5ec8482b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-08-02T22:29:41.584526Z",
     "iopub.status.busy": "2026-08-02T22:29:41.584432Z",
     "iopub.status.idle": "2026-08-02T22:29:41.586105Z",
     "shell.execute_reply": "2026-08-02T22:29:41.585884Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.30000000000000004\n",
      "Comparación directa: False\n",
      "Comparación tolerante: True\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "\n",
    "calculo = 0.1 + 0.2\n",
    "print(calculo)\n",
    "print(\"Comparación directa:\", calculo == 0.3)\n",
    "print(\"Comparación tolerante:\", math.isclose(calculo, 0.3))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a5a23521",
   "metadata": {},
   "source": [
    "## 4. Comparaciones, booleanos y verdad lógica\n",
    "\n",
    "Las comparaciones producen `True` o `False`. Se pueden encadenar y combinar con `and`, `or` y `not`. Python considera falsos, entre otros, `False`, `None`, cero y las colecciones vacías.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "0dc0dcc9",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-08-02T22:29:41.587559Z",
     "iopub.status.busy": "2026-08-02T22:29:41.587457Z",
     "iopub.status.idle": "2026-08-02T22:29:41.589448Z",
     "shell.execute_reply": "2026-08-02T22:29:41.589204Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "False\n",
      "True\n",
      "False True False True False\n"
     ]
    }
   ],
   "source": [
    "temperatura = 22\n",
    "es_confortable = 18 <= temperatura <= 25\n",
    "necesita_abrigo = temperatura < 15\n",
    "\n",
    "print(es_confortable)\n",
    "print(necesita_abrigo or temperatura < 18)\n",
    "print(not necesita_abrigo)\n",
    "print(bool(\"\"), bool(\"texto\"), bool(0), bool(12), bool(None))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "362e1ae1",
   "metadata": {},
   "source": [
    "## 5. Cadenas de texto\n",
    "\n",
    "`str` representa texto Unicode. Las cadenas son **inmutables**: los métodos crean una nueva cadena. Se accede a caracteres y fragmentos con índices y *slices*; el índice inicial es 0 y los índices negativos cuentan desde el final.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "358bb534",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-08-02T22:29:41.590787Z",
     "iopub.status.busy": "2026-08-02T22:29:41.590699Z",
     "iopub.status.idle": "2026-08-02T22:29:41.592483Z",
     "shell.execute_reply": "2026-08-02T22:29:41.592267Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "P n\n",
      "yth\n",
      "nohtyP\n",
      "Aprender python paso a paso\n",
      "  aprender Python paso a paso  \n"
     ]
    }
   ],
   "source": [
    "lenguaje = \"Python\"\n",
    "print(lenguaje[0], lenguaje[-1])\n",
    "print(lenguaje[1:4])\n",
    "print(lenguaje[::-1])\n",
    "\n",
    "mensaje = \"  aprender Python paso a paso  \"\n",
    "limpio = mensaje.strip().capitalize()\n",
    "print(limpio)\n",
    "print(mensaje)  # la cadena original no cambió\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01e8e34b",
   "metadata": {},
   "source": [
    "Métodos útiles: `lower`, `upper`, `strip`, `replace`, `split`, `join`, `startswith` y `endswith`. Para insertar valores de forma legible, las **f-strings** son la opción habitual.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "aa540982",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-08-02T22:29:41.593815Z",
     "iopub.status.busy": "2026-08-02T22:29:41.593723Z",
     "iopub.status.idle": "2026-08-02T22:29:41.595775Z",
     "shell.execute_reply": "2026-08-02T22:29:41.595556Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Lin compró 3 unidades: 59.85 €\n",
      "rojo | verde | azul\n"
     ]
    }
   ],
   "source": [
    "nombre = \"Lin\"\n",
    "unidades = 3\n",
    "precio = 19.95\n",
    "total = unidades * precio\n",
    "\n",
    "resumen = f\"{nombre} compró {unidades} unidades: {total:.2f} €\"\n",
    "palabras = \"rojo,verde,azul\".split(\",\")\n",
    "print(resumen)\n",
    "print(\" | \".join(palabras))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f931a8e0",
   "metadata": {},
   "source": [
    "## 6. `None`, identidad y conversiones\n",
    "\n",
    "`None` representa ausencia de valor. Se compara por identidad con `is None`, no con `== None`. Las funciones `int`, `float`, `str` y `bool` convierten cuando la conversión tiene sentido; una entrada inválida produce una excepción que veremos en el bloque 6.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "9abc3592",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-08-02T22:29:41.597080Z",
     "iopub.status.busy": "2026-08-02T22:29:41.596985Z",
     "iopub.status.idle": "2026-08-02T22:29:41.598928Z",
     "shell.execute_reply": "2026-08-02T22:29:41.598692Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "125 5.0 2026 str\n"
     ]
    }
   ],
   "source": [
    "resultado = None\n",
    "print(resultado is None)\n",
    "\n",
    "texto_entero = \"120\"\n",
    "entero = int(texto_entero)\n",
    "decimal = float(\"2.5\")\n",
    "etiqueta = str(2026)\n",
    "print(entero + 5, decimal * 2, etiqueta, type(etiqueta).__name__)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "199d6c7a",
   "metadata": {},
   "source": [
    "## Errores habituales\n",
    "\n",
    "- Confundir `=` (asignación) con `==` (comparación).\n",
    "- Mezclar texto y número sin convertir: `\"Edad: \" + 20` falla.\n",
    "- Comparar decimales binarios con igualdad exacta.\n",
    "- Reutilizar un nombre para valores de tipos sin relación.\n",
    "\n",
    "**Extensión opcional:** explora `decimal.Decimal` y `fractions.Fraction` en la biblioteca estándar.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0308a110",
   "metadata": {},
   "source": [
    "## Práctica · Resumen de una compra\n",
    "\n",
    "Dados un producto, un precio unitario, una cantidad y un descuento porcentual:\n",
    "\n",
    "1. Calcula subtotal, descuento e importe final.\n",
    "2. Crea una sola cadena con formato monetario de dos decimales.\n",
    "3. Comprueba que el total es positivo.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "ee35e44f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-08-02T22:29:41.600372Z",
     "iopub.status.busy": "2026-08-02T22:29:41.600281Z",
     "iopub.status.idle": "2026-08-02T22:29:41.601780Z",
     "shell.execute_reply": "2026-08-02T22:29:41.601557Z"
    },
    "tags": [
     "ejercicio"
    ]
   },
   "outputs": [],
   "source": [
    "# Punto de partida: completa el cuerpo y ejecuta tus pruebas.\n",
    "def resumir_compra(producto, precio_unitario, cantidad, descuento_pct):\n",
    "    # TODO: calcula y devuelve la cadena pedida.\n",
    "    pass\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "bee71c44",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-08-02T22:29:41.603001Z",
     "iopub.status.busy": "2026-08-02T22:29:41.602927Z",
     "iopub.status.idle": "2026-08-02T22:29:41.605244Z",
     "shell.execute_reply": "2026-08-02T22:29:41.605027Z"
    },
    "tags": [
     "solucion"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Cuaderno: subtotal=28.50 €, descuento=2.85 €, total=25.65 €, válido=True\n"
     ]
    }
   ],
   "source": [
    "# Solución posible\n",
    "def resumir_compra(producto, precio_unitario, cantidad, descuento_pct):\n",
    "    subtotal = precio_unitario * cantidad\n",
    "    descuento = subtotal * descuento_pct / 100\n",
    "    total = subtotal - descuento\n",
    "    es_valido = total > 0\n",
    "    return (\n",
    "        f\"{producto}: subtotal={subtotal:.2f} €, \"\n",
    "        f\"descuento={descuento:.2f} €, total={total:.2f} €, \"\n",
    "        f\"válido={es_valido}\"\n",
    "    )\n",
    "\n",
    "resumen = resumir_compra(\"Cuaderno\", 4.75, 6, 10)\n",
    "print(resumen)\n",
    "assert \"total=25.65 €\" in resumen\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6fb7a62",
   "metadata": {},
   "source": [
    "            ## Comprobación rápida\n",
    "\n",
    "            - [ ] Distingo `int`, `float`, `bool`, `str` y `None`.\n",
    "- [ ] Sé cuándo usar `=`, `==` e `is None`.\n",
    "- [ ] Puedo convertir y formatear valores.\n",
    "\n",
    "            [Volver al índice](README.md) · [Siguiente →](02_control_del_flujo.ipynb)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
