Categoría: Programación

  • 1.4 – Alcance de las Variables

    1.4 – Alcance de las Variables

    Bloques de código

    Hasta ahora, asumimos que después de declarar una variable, su nombre podría usarse en todo el código del programa (es decir, el alcance de la variable es global). Esto no es del todo cierto: el alcance de una variable depende de dónde se declare. Desafortunadamente, para una buena comprensión del alcance de una variable, necesitamos aprender algunos elementos de programación más, como instrucciones o funciones condicionales, que se analizarán con detalle más adelante en el curso. Así que aquí nos limitaremos a la información básica y volveremos a este tema en diferentes partes del curso. Uno de los elementos básicos que influyen en el alcance de las variables es un bloque del programa.

    Podemos separar el código de un programa en bloques. En los bloques que creamos usando llaves {}, hay un conjunto de instrucciones que, por alguna razón, deben tratarse de forma independiente. Los bloques suelen estar asociados a instrucciones condicionales, bucles o funciones. También podemos separar un bloque de un programa que no tenga nada en especial, simplemente eligiendo un determinado rango de instrucciones.

    {
        counter = 1;
     {
            console.log(counter); // -> 1
     }
    }

    Es hora de seguir adelante para determinar qué está pasando realmente con estos alcances. Desafortunadamente, los alcances de las variables (y constantes) declaradas con let y const son ligeramente diferentes a las declaradas con var. Así que los discutiremos de forma independiente.

    let y const

    En JavaScript, la declaración let const se utiliza para declarar variables que tienen un alcance de bloque. Esto significa que la variable sólo está disponible dentro del bloque de código en el que se ha declarado, y no está disponible en ningún otro lugar del programa.

    if (true) {
      let x = "hello";
      console.log(x); // "hello"
    }
    console.log(x); // ReferenceError: x is not defined

    En este ejemplo, la variable x se declara dentro del bloque de código del bloque if. Está disponible dentro del bloque y se puede acceder a ella en la primera línea de console.log(). Sin embargo, intentar acceder a x fuera del bloque de código del bloque if resulta en un error de referencia, ya que x no está definida en ese ámbito.

    El alcance de bloque también se aplica a los bucles for y a otras estructuras de control de flujo. Por ejemplo:

    for (let i = 0; i < 5; i++) {
      console.log(i); // 0, 1, 2, 3, 4
    }
    console.log(i); // ReferenceError: i is not defined

    En este ejemplo, la variable i se declara dentro del bloque de código del bucle for. Está disponible dentro del bucle y se puede acceder a ella en cada iteración. Sin embargo, intentar acceder a i fuera del bucle resulta en un error de referencia, ya que i no está definida en ese ámbito.

    En resumen, el alcance de una variable declarada con let es el bloque de código en el que se ha declarado. Fuera de ese bloque, la variable no está disponible y se produce un error de referencia si se intenta acceder a ella.

    var

    la declaración var se utiliza para declarar variables. A diferencia de la declaración let, que tiene un alcance de bloque, las variables declaradas con var tienen un alcance de función o global.

    Si se declara una variable con var dentro de una función, está disponible en toda la función. Por ejemplo:

    function foo() {
     if (true) {
     var x = "hello";
     }
      console.log(x); // "hello"
    }

    En este ejemplo, la variable x se declara dentro del bloque de código del bloque if, pero está disponible en toda la función foo(). Esto se debe a que el alcance de una variable declarada con var es la función en la que se ha declarado.

    Si se declara una variable con var fuera de una función, está disponible en todo el ámbito global. Por ejemplo:

    var x = "hello";
    function foo() {
      console.log(x); // "hello"
    }

    En este ejemplo, la variable x se declara fuera de cualquier función, por lo que tiene un alcance global. Está disponible en todo el código del programa y se puede acceder a ella desde cualquier función.

    Es importante tener en cuenta que el alcance de var puede dar lugar a comportamientos inesperados en algunos casos. Por ejemplo, si se declara una variable con var dentro de un bucle for, esta variable estará disponible en toda la función o el ámbito global, incluso después de que el bucle haya finalizado.

    for (var i = 0; i < 5; i++) {
     // ...
    }
    console.log(i); // 5

    En este ejemplo, la variable i se declara dentro del bucle for, pero está disponible en toda la función o el ámbito global. Esto puede dar lugar a comportamientos inesperados y es una de las principales razones por las que se recomienda utilizar let en lugar de var para declarar variables en JavaScript.

    En resumen, el alcance de una variable declarada con var es la función o el ámbito global en el que se ha declarado. Esto puede dar lugar a comportamientos inesperados en algunos casos y se recomienda utilizar let en su lugar, que tiene un alcance de bloque más predecible.

  • 1.5 – Objetos básicos en JavaScript

    1.5 – Objetos básicos en JavaScript

    En JavaScript existen objetos integrados que forman parte del núcleo del lenguaje. No necesitas crearlos: ya existen y puedes usarlos directamente.

    Los más importantes:

    • Math → cálculos matemáticos
    • Object → base de todos los objetos
    • Array → colecciones de datos
    • String → texto
    • Date → fechas y tiempo

    Acceso a propiedades y métodos

    Se usa el operador punto (.)

    Propiedad (dato)

    miObjeto.miPropiedad

    Método (acción)

    miObjeto.miMetodo(param1, param2)
    miObjeto.miMetodo()

    Objeto Math

    Sirve para realizar cálculos matemáticos. No se instancia.

    alert(Math.random());

    Genera número decimal entre 0 y 1

    letnumero=Math.floor(Math.random() *10);
    alert(numero);

    Métodos principales de Math

    MétodoQué haceEjemplo
    Math.random()Número aleatorio entre 0 y 1Math.random()
    Math.floor(n)Redondea hacia abajoMath.floor(4.9) → 4
    Math.ceil(n)Redondea hacia arribaMath.ceil(4.1) → 5
    Math.round(n)Redondeo normalMath.round(4.5) → 5
    Math.max(a,b)Mayor valorMath.max(5,10)
    Math.min(a,b)Menor valorMath.min(5,10)
    Math.pow(a,b)PotenciaMath.pow(2,3) → 8
    Math.sqrt(n)Raíz cuadradaMath.sqrt(16) → 4

    Objeto String

    Cuando creas texto, JavaScript crea un objeto String.

    let texto="Hola mundo";
    alert(texto.length);

    Métodos principales de String

    MétodoQué haceEjemplo
    lengthNúmero de caracteres"Hola".length → 4
    toUpperCase()Mayúsculas"hola".toUpperCase()
    toLowerCase()Minúsculas"HOLA".toLowerCase()
    includes(txt)Busca texto"JavaScript".includes("Script")
    indexOf(txt)Posición de texto"Hola".indexOf("o")
    substring(a,b)Extrae parte"Hola".substring(1,3)
    replace(a,b)Reemplaza"Hola".replace("o","0")
    trim()Quita espacios extremos" hola ".trim()

    Objeto Array

    Colecciones ordenadas de datos.

    let numeros= [10,20,30];
    numeros.push(40);

    Métodos principales de Array

    MétodoQué haceEjemplo
    lengthTamaño del array[1,2].length
    push(x)Añade al finalarr.push(5)
    pop()Elimina últimoarr.pop()
    shift()Elimina primeroarr.shift()
    unshift(x)Añade al inicioarr.unshift(0)
    includes(x)Comprueba existenciaarr.includes(10)
    indexOf(x)Posiciónarr.indexOf(20)
    join(sep)Convierte a textoarr.join(",")
    slice(a,b)Subarrayarr.slice(1,3)
    splice()Modifica arrayarr.splice(1,1)

    Objeto Object

    Es la base de todos los objetos en JavaScript.

    let persona= {nombre: "Ana",edad: 20};
    alert(persona.nombre);

    Métodos principales de Object

    MétodoQué haceEjemplo
    Object.keys(obj)Lista clavesObject.keys(persona)
    Object.values(obj)Lista valoresObject.values(persona)
    Object.entries(obj)Clave + valorObject.entries(persona)
    hasOwnProperty(k)Comprueba propiedadpersona.hasOwnProperty("edad")
    assign(a,b)Copia objetosObject.assign(a,b)

    Objeto Date

    El objeto Date representa fechas y tiempo. Internamente guarda milisegundos desde 1 enero 1970 (Unix Epoch).

    let ahora = new Date();
    alert(ahora);

    Crear fechas

    new Date()                      // Fecha actual
    new Date("2025-12-25")          // Desde texto
    new Date(2025, 0, 1)            // Año, mes(0-11), día

    Métodos principales de Date

    MétodoQué haceEjemplo
    getFullYear()Añofecha.getFullYear()
    getMonth()Mes (0-11)fecha.getMonth()
    getDate()Día del mesfecha.getDate()
    getDay()Día semana (0-6)fecha.getDay()
    getHours()Horafecha.getHours()
    getMinutes()Minutosfecha.getMinutes()
    getSeconds()Segundosfecha.getSeconds()
    getTime()Milisegundos desde 1970fecha.getTime()
    setFullYear(a)Cambia añofecha.setFullYear(2030)
    toLocaleDateString()Fecha formateadafecha.toLocaleDateString()
    toLocaleTimeString()Hora formateadafecha.toLocaleTimeString()

    Ejemplo práctico Date

    let ahora = new Date();
    
    let mensaje =
      "Hoy es: " + ahora.toLocaleDateString() +
      "\nHora: " + ahora.toLocaleTimeString();
    
    alert(mensaje);

    Concepto clave

    En JavaScript:

    • Las propiedades describen
    • Los métodos actúan

    Ejemplo:

    texto.length        → dato
    texto.toUpperCase() → acción
    fecha.getFullYear() → acción sobre el tiempo

    Otros objetos disponibles en JavaScript

    ObjetoQué esPara qué se usaEjemplo rápido
    NumberRepresenta númerosOperaciones numéricas, conversionesNumber("10")
    BooleanValores verdadero/falsoLógica condicionalBoolean(1)
    RegExpExpresiones regularesBuscar y validar texto/[a-z]+/.test("hola")
    JSONManejo de datos JSONConvertir objetos ↔ textoJSON.parse(txt)
    MapColección clave → valorEstructuras tipo diccionariomap.set("a",1)
    SetColección sin duplicadosListas únicasset.add(5)
    PromiseOperaciones asíncronasFetch, AJAX, temporizadoresfetch(url)
    FunctionFunciones como objetosProgramación funcionaltypeof f === "function"
    ErrorManejo de errorestry/catchthrow new Error()
    SymbolIdentificadores únicosPropiedades privadasSymbol("id")
    BigIntEnteros muy grandesCriptografía, cálculos grandes123n
    URLManipulación de URLsLeer parámetrosnew URL(location)
    FormDataDatos de formulariosEnvío POSTnew FormData(form)
    DateTiempo y fechasCalendario, relojesnew Date()
    MathMatemáticasCálculosMath.random()

    • JSON → traductor entre objetos y texto
    • Map vs Object → Map está optimizado para colecciones dinámicas
    • Set → evita duplicados automáticamente
    • Promise → permite esperar resultados sin bloquear el programa
    • RegExp → motor de búsqueda textual extremadamente potente
    • Symbol → claves invisibles para evitar colisiones
    • BigInt → números más allá del límite de Number

    Ejemplos

    JSON

    let texto = '{"nombre":"Ana"}';
    let obj = JSON.parse(texto);
    alert(obj.nombre);

    Map

    let mapa = new Map();
    mapa.set("usuario", "admin");
    alert(mapa.get("usuario"));

    Set

    let mapa = new Map();
    mapa.set("usuario", "admin");
    alert(mapa.get("usuario"));

    Promise (idea básica)

    fetch("datos.json")
      .then(r => r.json())
      .then(datos => console.log(datos));

    Ejercicios

    Ejercicio 1

    Mostrar un número aleatorio del 1 al 100.

    Ejercicio 2

    Crear un texto con tu nombre y mostrar:

    • Longitud
    • En mayúsculas
    • Si contiene la letra «a»

    Ejercicio 3

    Crear un array con 3 números y:

    • Añadir uno
    • Mostrar tamaño
    • Mostrar si contiene el número 5

    Ejercicio 4

    Mostrar:

    • Año actual
    • Mes actual
    • Hora actual
  • 1.6 – Arrays en JavaScript

    1.6 – Arrays en JavaScript

    Un array es una estructura que permite almacenar múltiples valores en una sola variable.

    Puede contener:

    • Números
    • Texto
    • Objetos
    • Otros arrays
    • Mezclas de todo (JavaScript no es quisquilloso)

    Crear un array

    let numeros= [10, 20, 30];

    También:

    letvacio= [];

    O usando el constructor:

    let lista=new Array(1,2,3);

    Acceder a elementos

    Los arrays empiezan en índice 0 (como casi todo en informática).

    let colores = ["rojo", "verde", "azul"];
    
    alert(colores[0]); // rojo
    alert(colores[2]); // azul

    Propiedad fundamental

    let numeros = [1,2,3,4];
    alert(numeros.length);

    length → número de elementos


    Métodos principales de Array

    Añadir y eliminar

    let lista = [10,20];
    
    lista.push(30);   // añade al final
    lista.pop();      // elimina último
    lista.unshift(5); // añade al inicio
    lista.shift();    // elimina primero

    Buscar elementos

    let numeros = [10,20,30];
    
    numeros.includes(20); // true
    numeros.indexOf(30);  // 2

    Convertir a texto

    let colores = ["rojo","verde","azul"];
    alert(colores.join(" - "));

    Resultado:

    rojo - verde - azul

    Extraer partes

    let datos = [1,2,3,4,5];
    
    let sub = datos.slice(1,4); // [2,3,4]

    slice no modifica el original.


    Modificar el array

    let datos = [1,2,3,4];
    
    datos.splice(1,2); // elimina desde posición 1 → elimina 2 elementos

    Resultado:

    [1,4]

    Video Arrays

    Tabla completa de métodos importantes

    MétodoQué haceEjemplo
    lengthTamaño del array[1,2].length
    push(x)Añade al finalarr.push(5)
    pop()Elimina últimoarr.pop()
    shift()Elimina primeroarr.shift()
    unshift(x)Añade al inicioarr.unshift(0)
    includes(x)Comprueba existenciaarr.includes(10)
    indexOf(x)Posición del valorarr.indexOf(20)
    join(sep)Convierte a textoarr.join(",")
    slice(a,b)Subarray sin modificararr.slice(1,3)
    splice(a,b)Modifica/elimina/añadearr.splice(1,1)
    reverse()Invierte arrayarr.reverse()
    sort()Ordenaarr.sort()
    concat()Une arraysa.concat(b)
    forEach()Recorre arrayarr.forEach(f)
    map()Transforma elementosarr.map(f)
    filter()Filtra elementosarr.filter(f)
    find()Encuentra elementoarr.find(f)

    Recorrer arrays

    Método clásico

    let numeros = [10,20,30];
    
    for (let i = 0; i < numeros.length; i++) {
      console.log(numeros[i]);
    }

    forEach

    numeros.forEach(function(n) {
      console.log(n);
    });

    map (transformar)

    let dobles = numeros.map(n => n * 2);

    filter (filtrar)

    let mayores = numeros.filter(n => n > 15);

    Arrays con objetos

    let alumnos = [
      {nombre:"Ana", nota:8},
      {nombre:"Luis", nota:5}
    ];
    
    console.log(alumnos[0].nombre);

    Esto es el paso previo al JSON del backend → DOM


    Conceptos clave

    • Los arrays pueden crecer dinámicamente
    • Pueden contener cualquier tipo
    • Son objetos (typeof array → "object")
    • map/filter/find son la base del JavaScript moderno

    Ejercicios para alumnos

    Ejercicio 1

    Crear un array con 5 números y mostrar el tamaño.

    Ejercicio 2

    Añadir un número y eliminar el primero.

    Ejercicio 3

    Mostrar solo los números mayores que 10.

    Ejercicio 4

    Crear un array de nombres y convertirlos a mayúsculas con map.

    Ejercicio 5

    Crear un array de objetos alumno {nombre, nota} y mostrar solo los aprobados.

  • 1.7 – Funciones con JS

    1.7 – Funciones con JS

    Una función es un bloque de código reutilizable que ejecuta una tarea concreta.
    Sirve para organizar, reutilizar y abstraer lógica.

    Idea clave: no repitas código, encapsúlalo.

    Ejemplo mental: una cafetera.
    Entras agua + café → proceso → sale café.
    La función hace exactamente eso, pero con datos.


    2. Sintaxis básica

    function nombreFuncion() {
        // código a ejecutar
    }

    Ejemplo:

    function saludar() {
        console.log("Hola mundo");
    }

    La función no se ejecuta sola. Hay que llamarla:

    saludar();

    3. Funciones con parámetros

    Los parámetros son datos que recibe la función.

    function saludar(nombre) {
        console.log("Hola " + nombre);
    }
    
    saludar("Antonio");
    saludar("Bea");

    La función se adapta al dato. Eso es abstracción.


    4. Retorno de valores (return)

    Una función puede devolver un resultado.

    function saludar(nombre) {
        console.log("Hola " + nombre);
    }
    
    saludar("Antonio");
    saludar("Bea");

    Sin return, la función devuelve undefined.

    Concepto importante:
    return termina la ejecución de la función.


    5. Parámetros vs argumentos

    • Parámetros → variables definidas en la función
    • Argumentos → valores reales que se pasan al llamar
    functionmultiplicar(x, y) {   // parámetrosreturnx*y;}multiplicar(4, 2);             // argumentos

    6. Funciones que llaman a otras funciones

    Las funciones pueden componer comportamiento.

    function cuadrado(n) {
        return n * n;
    }
    
    function mostrarCuadrado(num) {
        let resultado = cuadrado(num);
        console.log(resultado);
    }
    
    mostrarCuadrado(5);

    Esto es modularidad. Construir piezas pequeñas y combinarlas.


    7. Funciones anónimas

    Funciones sin nombre, normalmente guardadas en variables.

    let saludar = function(nombre) {
        return "Hola " + nombre;
    };
    
    console.log(saludar("Carlos"));

    8. Arrow functions (funciones flecha)

    Forma moderna y compacta.

    let sumar = (a, b) => {
        return a + b;
    };

    Si solo hay una línea:

    let sumar = (a, b) => {
        return a + b;
    };

    Si solo hay un parámetro:

    let cuadrado = n => n * n;

    9. Ámbito (scope)

    El scope define dónde existe una variable.

    function prueba() {
        let x = 10;
        console.log(x);
    }
    
    prueba();
    console.log(x); // ERROR

    x solo vive dentro de la función.
    Esto protege el programa de efectos colaterales.


    10. Buenas prácticas

    Nombres claros

    Mal:

    functionf(x) {}

    Bien:

    function calcularTotal(precio, iva) {}

    Funciones pequeñas

    Una función debe hacer una sola cosa.


    Evitar repetir código

    Si copias y pegas → necesitas una función.


    11. Ejemplos prácticos

    Calcular precio con IVA

    function calcularPrecioConIVA(precio) {
        return precio * 1.21;
    }
    
    console.log(calcularPrecioConIVA(100));

    Verificar si un número es par

    function esPar(numero) {
        return numero % 2 === 0;
    }
    
    console.log(esPar(4));
    console.log(esPar(7));

    Convertir JSON recibido del backend (pensando en JEE)

    function pintarUsuario(usuario) {
        console.log("Nombre: " + usuario.nombre);
        console.log("Email: " + usuario.email);
    }
    
    let json = {
        nombre: "Antonio",
        email: "antonio@email.com"
    };
    
    pintarUsuario(json);

    Aquí empieza el puente hacia DOM + datos del servidor.


    12. Ejercicios

    1. Crear función que calcule el área de un rectángulo
    2. Crear función que convierta grados Celsius a Fahrenheit
    3. Crear función que reciba un nombre y devuelva: "Bienvenido <nombre>"
    4. Crear función que reciba un array y devuelva la suma total
  • 2.1 – JSON: Formato de intercambio y almacenamiento de datos

    2.1 – JSON: Formato de intercambio y almacenamiento de datos

    JSON (JavaScript Object Notation) es un formato de texto basado en la estructura de objetos de JavaScript. Más moderno y ligero que XML, se utiliza ampliamente tanto para la transmisión de datos entre aplicaciones como para su almacenamiento.

    Este modelo de datos se ha popularizado porque prioriza el contenido sobre la estructura, reduciendo la cantidad de sintaxis necesaria y facilitando la lectura por parte de humanos y máquinas.


    Estructura básica

    Un archivo JSON es una cadena de texto que debe parsearse (analizarse sintácticamente) para acceder a sus datos. Este proceso se denomina parsing cuando convertimos una cadena en un objeto, y stringification cuando hacemos la operación inversa (objeto → texto).

    Los principales elementos de la estructura JSON son:

    • {}: delimitan un objeto.
    • []: delimitan un array (lista ordenada de elementos).
    • :: separa las claves de sus valores.
    • ,: separa los diferentes pares de clave-valor o elementos.
    • "": delimitan los valores de texto (string).

    Ejemplo de objeto JSON

    {
      "squadName": "Super hero squad",
      "homeTown": "Metro City",
      "formed": 2016,
      "secretBase": "Super tower",
      "active": true,
      "members": [
        {
          "name": "Molecule Man",
          "age": 29,
          "secretIdentity": "Dan Jukes",
          "powers": ["Radiation resistance", "Turning tiny", "Radiation blast"]
        },
        {
          "name": "Madame Uppercut",
          "age": 39,
          "secretIdentity": "Jane Wilson",
          "powers": ["Million tonne punch", "Damage resistance", "Superhuman reflexes"]
        },
        {
          "name": "Eternal Flame",
          "age": 1000000,
          "secretIdentity": "Unknown",
          "powers": ["Immortality", "Heat Immunity", "Inferno", "Teleportation", "Interdimensional travel"]
        }
      ]
    }
    

    Reglas básicas para crear archivos JSON

    1. Los datos se organizan en pares clave:valor, separados por comas.
    2. Tanto claves como valores de texto van entre comillas dobles («»).
    3. Los objetos se delimitan con llaves {}.
    4. Los arrays se delimitan con corchetes [].
    5. Los objetos y arrays pueden anidarse entre sí.

    Ejemplo:

    {
      "nombre": "Jose",
      "edad": 20,
      "genero": "masculino",
      "email": "correodejose@dominio.com",
      "localidad": "Madrid",
      "telefono": "91000000",
      "mando": true,
      "marco": "<iframe width=560 height=315 src='https://www.youtube.com/embed/QCEU-vba8mw' frameborder=0 allowfullscreen></iframe>"
    }
    

    Objetos y arrays en JSON

    • Objeto: se define con llaves {} y contiene uno o varios pares clave-valor.json{ "nombre": "Juan", "apellidos": "Gonzalez" }
    • Array: se define con corchetes [] y puede incluir valores o incluso objetos.json{ "nombre": "Juan", "edad": 30, "coches": ["Ford", "BMW", "Fiat"] }
    • Array de objetos:json{ "nombre": "Juan", "edad": 30, "coches": [ { "nombre": "Ford", "modelos": ["Fiesta", "Focus", "Mustang"] }, { "nombre": "BMW", "modelos": ["320", "X3", "X5"] }, { "nombre": "Fiat", "modelos": ["500", "Panda"] } ] }

    Tipos de datos permitidos

    • string: cadenas de texto.
    • number: números enteros o decimales.
    • object: objetos JSON.
    • array: listas ordenadas.
    • boolean: valores true o false.
    • null: valor nulo o sin asignar.

    JSON vs XML

    JSON y XML son formatos ampliamente usados para intercambiar información entre sistemas y almacenar configuraciones o datos estructurados.

    Aunque JSON suele ser más ligero y fácil de leer, XML ofrece ventajas en casos donde se necesita validación mediante esquemas (XSD) o metadatos complejos.

    Ejemplo JSON:

    {
      "employees": [
        { "firstName": "John", "lastName": "Doe" },
        { "firstName": "Anna", "lastName": "Smith" },
        { "firstName": "Peter", "lastName": "Jones" }
      ]
    }
    

    Ejemplo XML:

    <employees>
      <employee>
        <firstName>John</firstName>
        <lastName>Doe</lastName>
      </employee>
      <employee>
        <firstName>Anna</firstName>
        <lastName>Smith</lastName>
      </employee>
      <employee>
        <firstName>Peter</firstName>
        <lastName>Jones</lastName>
      </employee>
    </employees>
    

    En general, JSON es ideal para intercambio rápido de datos entre aplicaciones web, mientras que XML puede ser preferible en entornos donde se requiera validación formal o compatibilidad con sistemas antiguos.

  • Actividad – Json Invertido

    Actividad – Json Invertido

    Tu tarea es analizar el siguiente código JavaScript y crear el archivo JSON correcto para que funcione sin errores.

    EJERCICIO 1

     Código JavaScript (index.html + script.js)

    Guarda estos archivos y ábrelos en un navegador. (Es  necesario que utilices modo servidor como un contendor o XAMPP)

    https://drive.google.com/file/d/1tK86N1EGZlHKjtxSIHV0TJZ4IcgYyWMd/view?usp=sharingLinks to an external site.

    Si el JSON está bien hecho, al abrir index.html en el navegador debería mostrarse:

    Lista de Productos

    • Tarta de Chocolate – $15 – Stock: 10
    • Cheesecake – $12 – Stock: 5
    • Brownie – $8 – Stock: 7

    EJERCICIO 2

    Tu tarea es analizar el código JavaScript y crear el archivo JSON correcto para que funcione sin errores.

    Código JavaScript (index.html + script.js)

    Guarda estos archivos y ábrelos en un navegador.

    https://drive.google.com/file/d/1spFSlotW1K6Cnm-N5LejSGQhn79phaAd/view?usp=sharingLinks to an external site.

  • Reto –  “Madrid bajo cero”

    Reto – “Madrid bajo cero”

    Hoy ha nevado en Madrid. El ayuntamiento quiere un pequeño programa en Java para registrar datos comunes de la nevada, sin entrar en sistemas complejos ni lógica avanzada.

    Repasa la documentación sobre este reto: https://laaventuradeaprender.com/una-clase-una-instancia-y-cero-excusas-static-y-singleton-en-java/

    EstacionMeteorologica

    Crear una clase llamada EstacionMeteorologica.
    Cada estación representa un punto de medición distinto de Madrid (Sol, Chamartín, Moncloa…), pero hay datos que son globales, iguales para todas las estaciones.

    1. Crea una clase llamada EstacionMeteorologica.
    2. Cada estación tendrá un atributo que es su numero de serie
    3. Añade los siguientes atributos estáticos:
      • ciudad (String) → siempre será "Madrid"
      • temperaturaMedia (double)
      • nevadaActiva (boolean)
    4. Crea solo un constructor vacío (no parámetros).
    5. En el main:
      • Asigna valores a los atributos estáticos usando el nombre de la clase.
      • Crea al menos tres objetos de EstacionMeteorologica.
      • Muestra por pantalla los valores de los atributos estáticos desde cada objeto.

    Reglas del reto

    • No usar métodos static (solo atributos).
    • No usar herencia.
    • No usar arrays, listas ni entrada por teclado.
    • No usar getters ni setters.
    • No usar lógica condicional (if, switch, etc.)

    Ejemplo de salida esperada (orientativa)

    Ciudad: Madrid
    Numero de serie: 124
    Temperatura media: -1.5
    Nevada activa: true
    
    Ciudad: Madrid
    Numero de serie: 234
    Temperatura media: -1.5
    Nevada activa: true

    Emergencia por nieve en Madrid

    Tras la nevada, el ayuntamiento necesita acciones rápidas y globales: avisar a la población, consultar el estado general y actualizar la temperatura.
    Estas acciones no dependen de una estación concreta, sino del estado general de la ciudad.

    Se trabaja con una clase llamada CentroEmergencias.
    No representa un objeto físico concreto, sino un servicio global que actúa sobre el estado general de Madrid.

    1. Crea una clase llamada CentroEmergencias.
    2. Añade los siguientes atributos estáticos:
      • ciudad (String) → "Madrid"
      • temperatura (double)
      • nevadaActiva (boolean)
    3. Añade los siguientes métodos estáticos:
      • activarNevada() → pone nevadaActiva a true
      • desactivarNevada() → pone nevadaActiva a false
      • actualizarTemperatura(double t)
      • mostrarEstado() → muestra todos los datos por pantalla
    4. En el main:
      • Llama a los métodos sin crear ningún objeto.
      • Cambia el estado varias veces.
      • Muestra el estado tras cada cambio.

    Ejemplo de ejecución esperada (orientativa)

    Ciudad: Madrid
    Temperatura: -2.0
    Nevada activa: false
    
    Activando nevada...
    
    Ciudad: Madrid
    Temperatura: -2.0
    Nevada activa: true
    
    Actualizando temperatura...
    
    Ciudad: Madrid
    Temperatura: -4.5
    Nevada activa: true

    Parte meteorológico express

    Tras la nevada, los medios necesitan cálculos rápidos y mensajes claros, pero no quieren guardar estado.
    Solo quieren usar herramientas que reciban datos, hagan su trabajo y desaparezcan sin dejar rastro.

    El objetivo del reto es entender que un método static puede existir sin ningún atributo static.

    Se crea una clase llamada InformeNieve.
    Esta clase no guarda información, solo procesa datos que se le pasan y devuelve resultados o muestra mensajes.

    Es una clase “herramienta”, no un objeto con estado.

    Crea una clase llamada InformeNieve.

    No declares ningún atributo (ni estático ni no estático).

    Crea los siguientes métodos estáticos:

    • mostrarAviso(double temperatura)
    • convertirCelsiusAFahrenheit(double celsius)
    • calcularSensacionTermica(double temperatura, double viento)

    En el main:

    • Llama a los métodos directamente usando el nombre de la clase.
    • Usa valores literales (números escritos directamente).
    • Muestra los resultados por pantalla.

    Reglas del reto

    • Prohibido declarar atributos.
    • Prohibido usar new.
    • Prohibido usar getters, setters o constructores.
    • No usar colecciones ni entrada por teclado.
    • Mantener los métodos simples y claros.

    Ejemplo de uso

    Aviso: Temperatura crítica (-3.0 ºC)
    
    Temperatura en Fahrenheit: 26.6
    
    Sensación térmica estimada: -8.5 ºC

    Este reto es deliberadamente austero.

    “El Quitanieves Supremo de Madrid” (Singleton)

    Madrid ha amanecido blanco. El ayuntamiento activa un único centro de control que coordina todo: no puede haber dos, porque acabarían pisándose órdenes (y eso en una nevada acaba en caos).

    Vas a crear la clase CentroQuitanieves que gestiona el estado de la emergencia:

    • cuántas máquinas quitanieves están activas
    • cuántas toneladas de sal se han repartido
    • cuántos avisos se han emitido

    Todo eso debe estar dentro de una única instancia.

    1. Crea la clase CentroQuitanieves.
    2. Implementa Singleton clásico:
      • atributo privado static para la instancia
      • constructor private
      • método public static CentroQuitanieves getInstancia()
    3. Añade atributos NO estáticos (del objeto único):
      • int maquinasActivas
      • int toneladasSal
      • int avisosEmitidos
    4. Añade métodos (no estáticos) simples:
      • activarMaquina() → suma 1 a maquinasActivas
      • repartirSal(int toneladas) → suma a toneladasSal
      • emitirAviso() → suma 1 a avisosEmitidos
      • mostrarResumen() → imprime todos los datos
    • No puedes hacer new CentroQuitanieves()
    • Debes pedir el centro así:
    CentroQuitanieves c1 = CentroQuitanieves.getInstancia();
    CentroQuitanieves c2 = CentroQuitanieves.getInstancia();
    
    • Comprueba que es el mismo objeto:
    System.out.println(c1 == c2); // debería ser true
    
    • Realiza acciones con c1 y muestra el resumen con c2 (o al revés) para comprobar que comparten estado.

    Ejemplo de salida:

    ¿Mismo centro? true
    
    Resumen Madrid:
    Máquinas activas: 2
    Toneladas de sal: 15
    Avisos emitidos: 3
  • Una clase, una instancia y cero excusas: static y Singleton en Java

    Una clase, una instancia y cero excusas: static y Singleton en Java

    Un atributo static es un atributo que pertenece a la clase, no a los objetos creados a partir de ella.
    Existe una única copia del atributo para toda la aplicación, compartida por todas las instancias.

    • Se declara con la palabra clave static.
    • Se accede usando el nombre de la clase.
    • No depende de ningún objeto concreto.
    • Se inicializa cuando la clase se carga en memoria.

    Cuándo usarlo

    • Contadores globales.
    • Constantes compartidas.
    • Información común a todos los objetos.
    • Estados que deben ser únicos para la clase.

    public class Jugador {
        private String nombre;
        private int puntos;
        public static int totalJugadores = 0;
    
        public Jugador(String nombre) {
            this.nombre = nombre;
            this.puntos = 0;
            totalJugadores++; // actualiza el contador compartido
        }
    }
    


    Si luego haces:

    new Jugador("Ana");
    new Jugador("Luis");
    System.out.println(Jugador.totalJugadores); // Imprime 2
    Da igual cuántos jugadores existan o cuáles sean sus puntos: el contador es único.

    Este tipo de atributo se usa cuando algo pertenece conceptualmente a la clase como conjunto, no a cada objeto. Desde aquí la curiosidad lleva a campos como los métodos static, inicialización estática y patrones de diseño como Singleton o constantes globales, donde las clases juegan a ser “contenedores” más que “plantillas de objetos”.

    Errores comunes

    • Usar static para guardar datos que deberían ser propios de cada objeto.
    • Acceder a un atributo estático usando una instancia en vez de la clase.

    Métodos static en Java

    Un método static es un método que pertenece a la clase, no a los objetos.
    Se puede ejecutar sin crear ninguna instancia.

    • Se llama directamente desde la clase.
    • No puede usar this.
    • No puede acceder directamente a atributos no estáticos.
    • Ideal para lógica independiente del estado de los objetos.

    Cuándo usarlo

    • Métodos de utilidad (cálculos, conversiones, validaciones).
    • Operaciones matemáticas o lógicas puras.
    • Métodos fábrica.
    • Acceso a recursos compartidos.
    public class Conversor {
        public static double celsiusAFahrenheit(double c) {
            return (c * 9/5) + 32;
        }
    }
    double f = Conversor.celsiusAFahrenheit(20);
    System.out.println(f); // 68.0

    Diferencia clave frente a métodos normales

    Un método normal trabaja sobre un objeto concreto.
    Un método static trabaja sobre la idea de la clase.


    Relación entre static y diseño de clases

    • Lo no estático representa el estado individual de cada objeto.
    • Lo estático representa el estado o comportamiento global de la clase.

    Entender esta diferencia es fundamental para:

    • Diseñar bien las clases.
    • Evitar estado global innecesario.
    • Preparar el terreno para patrones de diseño.

    Introducción al patrón Singleton

    El patrón Singleton garantiza que una clase tenga una única instancia y proporciona un punto de acceso global a ella.

    Por qué existe

    Hay elementos del sistema que deben existir una sola vez:

    • Configuración global.
    • Logger.
    • Gestor de recursos.
    • Controladores centrales.

    Características básicas

    • Constructor privado (no se puede usar new desde fuera).
    • Atributo static que guarda la única instancia.
    • Método static que devuelve esa instancia.

    Qué problema resuelve

    • Crear múltiples objetos que representan lo mismo.
    • Inconsistencias de estado.
    • Accesos descontrolados a recursos compartidos.

    Singleton y static: conexión directa

    El patrón Singleton combina directamente los conceptos vistos:

    • Usa un atributo static para almacenar la instancia única.
    • Usa un método static como punto de acceso.
    • Refuerza la idea de que algunas cosas pertenecen a la clase, no a los objetos.

    Ejemplo

    1. La clase se crea a sí misma por dentro.
    2. La clase guarda la única instancia en un atributo estático.
    3. Como el constructor es privado, nadie puede hacer new.
    4. Se accede usando un método static que devuelve siempre la misma instancia.

    Un ejemplo:

    public class Configuracion {
    
        // La única instancia
        private static Configuracion instancia;
    
        // Constructor privado para evitar new desde fuera
        private Configuracion() {
            // Inicialización
        }
    
        // Punto de acceso controlado
        public static Configuracion getInstancia() {
            if (instancia == null) {
                instancia = new Configuracion();
            }
            return instancia;
        }
    
        public void saludar() {
            System.out.println("Soy la única configuración.");
        }
    }
    

    Uso:

    Configuracion c1 = Configuracion.getInstancia();
    Configuracion c2 = Configuracion.getInstancia();
    
    System.out.println(c1 == c2); // true
    

    Ese true es la prueba de que ambos apuntan al mismo objeto.

    Singleton = una clase que garantiza una sola instancia y un único punto de acceso.


  • R7 [Solución] – Guerra por el Sistema Solar: Tierra, Marte y el Cinturón” (The Expanse)

    1) Nave.java

    
    
    
    
    
    /**
     * Representa una nave espacial dentro del universo de The Expanse.
     * 
     * Conceptos que se trabajan aquí:
     * - Encapsulamiento (atributos privados + getters/setters)
     * - Constructor completo
     * - toString() para imprimir bonito el objeto
     */
    public class Nave {
    
        // -------------------------
        // Atributos (siempre privados)
        // -------------------------
        private String nombre;
        private String faccion; // "Tierra", "Marte", "Cinturon"
        private int misiles;
        private boolean necesitaReparacion;
    
        // -------------------------
        // Constructores
        // -------------------------
    
        /**
         * Constructor completo exigido por el enunciado.
         */
        public Nave(String nombre, String faccion, int misiles, boolean necesitaReparacion) {
            this.nombre = nombre;
            this.faccion = faccion;
            this.misiles = misiles;
            this.necesitaReparacion = necesitaReparacion;
        }
    
        /**
         * Constructor opcional de conveniencia (por si quieres crear naves “rápido”).
         * Por ejemplo: misiles = 0 y no necesita reparación por defecto.
         */
        public Nave(String nombre, String faccion) {
            this(nombre, faccion, 0, false);
        }
    
        // -------------------------
        // Getters y Setters
        // -------------------------
        public String getNombre() {
            return nombre;
        }
    
        public void setNombre(String nombre) {
            this.nombre = nombre;
        }
    
        public String getFaccion() {
            return faccion;
        }
    
        public void setFaccion(String faccion) {
            this.faccion = faccion;
        }
    
        public int getMisiles() {
            return misiles;
        }
    
        public void setMisiles(int misiles) {
            this.misiles = misiles;
        }
    
        public boolean isNecesitaReparacion() {
            return necesitaReparacion;
        }
    
        public void setNecesitaReparacion(boolean necesitaReparacion) {
            this.necesitaReparacion = necesitaReparacion;
        }
    
        // -------------------------
        // toString() (muy útil para listar)
        // -------------------------
        @Override
        public String toString() {
            return "Nave{" +
                    "nombre='" + nombre + '\'' +
                    ", faccion='" + faccion + '\'' +
                    ", misiles=" + misiles +
                    ", necesitaReparacion=" + (necesitaReparacion ? "Sí" : "No") +
                    '}';
        }
    }
    

    2) Flota.java

    
    
    
    
    
    import java.util.ArrayList;
    import java.util.Scanner;
    
    /**
     * Flota = conjunto de naves.
     *
     * Conceptos que se trabajan:
     * - ArrayList con objetos (ArrayList<Nave>)
     * - Métodos para recorrer y filtrar
     * - Métodos con Scanner para crear objetos desde teclado
     */
    public class Flota {
    
        // Lista privada: nadie fuera debería tocarla directamente
        private ArrayList<Nave> naves;
    
        // -------------------------
        // Constructor
        // -------------------------
        public Flota() {
            // Inicializamos la lista vacía (obligatorio)
            this.naves = new ArrayList<>();
        }
    
        // -------------------------
        // Agregar nave ya creada
        // -------------------------
        public void agregarNave(Nave nave) {
            if (nave == null) {
                System.out.println("No se puede añadir una nave nula.");
                return;
            }
            naves.add(nave);
            System.out.println("✅ Nave añadida a la flota: " + nave.getNombre());
        }
    
        // -------------------------
        // Crear nave por teclado
        // -------------------------
        public void crearNaveDesdeTeclado(Scanner sc) {
            System.out.println("=== CREAR NUEVA NAVE ===");
    
            // Nombre
            System.out.print("Nombre de la nave: ");
            String nombre = sc.nextLine().trim();
    
            // Facción (validada)
            String faccion = leerFaccionValida(sc);
    
            // Misiles (entero >= 0)
            int misiles = leerEnteroNoNegativo(sc, "Número de misiles: ");
    
            // Reparación (S/N)
            boolean necesitaReparacion = leerBooleanSN(sc, "¿Necesita reparación? (S/N): ");
    
            // Creamos el objeto Nave con los datos recogidos
            Nave nave = new Nave(nombre, faccion, misiles, necesitaReparacion);
    
            // La añadimos al ArrayList
            naves.add(nave);
    
            System.out.println("✅ Nave creada y añadida: " + nave);
        }
    
        // -------------------------
        // Número de naves
        // -------------------------
        public int getNumeroNaves() {
            return naves.size();
        }
    
        // -------------------------
        // Listar todas
        // -------------------------
        public void listarTodas() {
            System.out.println("=== LISTADO COMPLETO DE NAVES ===");
    
            if (naves.isEmpty()) {
                System.out.println("La flota está vacía.");
                return;
            }
    
            for (Nave n : naves) {
                System.out.println(n); // llama a toString()
            }
        }
    
        // -------------------------
        // Listar naves para reparar
        // -------------------------
        public void listarNavesParaReparar() {
            System.out.println("=== NAVES QUE NECESITAN REPARACIÓN ===");
    
            boolean hay = false;
    
            for (Nave n : naves) {
                if (n.isNecesitaReparacion()) {
                    System.out.println(n);
                    hay = true;
                }
            }
    
            if (!hay) {
                System.out.println("No hay naves marcadas para reparación.");
            }
        }
    
        // -------------------------
        // Total de misiles
        // -------------------------
        public int getTotalMisiles() {
            int total = 0;
            for (Nave n : naves) {
                total += n.getMisiles();
            }
            return total;
        }
    
        // -------------------------
        // Listar por facción
        // -------------------------
        public void listarPorFaccion(String faccion) {
            System.out.println("=== NAVES DE LA FACCIÓN: " + faccion + " ===");
    
            boolean hay = false;
    
            for (Nave n : naves) {
                // equalsIgnoreCase = compara ignorando mayúsculas/minúsculas
                if (n.getFaccion().equalsIgnoreCase(faccion)) {
                    System.out.println(n);
                    hay = true;
                }
            }
    
            if (!hay) {
                System.out.println("No se encontraron naves de esa facción.");
            }
        }
    
        // -------------------------
        // Contar por facción
        // -------------------------
        public int contarPorFaccion(String faccion) {
            int contador = 0;
    
            for (Nave n : naves) {
                if (n.getFaccion().equalsIgnoreCase(faccion)) {
                    contador++;
                }
            }
    
            return contador;
        }
    
        // ==========================================================
        // Métodos auxiliares (para que el código quede limpio y robusto)
        // ==========================================================
    
        /**
         * Pide al usuario una facción válida: Tierra / Marte / Cinturon.
         */
        private String leerFaccionValida(Scanner sc) {
            while (true) {
                System.out.print("Facción (Tierra/Marte/Cinturon): ");
                String faccion = sc.nextLine().trim();
    
                if (esFaccionValida(faccion)) {
                    // Normalizamos para que quede bonito y consistente
                    return normalizarFaccion(faccion);
                }
    
                System.out.println("❌ Facción no válida. Usa: Tierra, Marte o Cinturon.");
            }
        }
    
        private boolean esFaccionValida(String faccion) {
            String f = faccion.trim().toLowerCase();
            return f.equals("tierra") || f.equals("marte") || f.equals("cinturon");
        }
    
        private String normalizarFaccion(String faccion) {
            String f = faccion.trim().toLowerCase();
            if (f.equals("tierra")) return "Tierra";
            if (f.equals("marte")) return "Marte";
            return "Cinturon";
        }
    
        /**
         * Lee un entero >= 0, repitiendo hasta que sea válido.
         */
        private int leerEnteroNoNegativo(Scanner sc, String mensaje) {
            while (true) {
                System.out.print(mensaje);
                String linea = sc.nextLine().trim();
    
                try {
                    int valor = Integer.parseInt(linea);
                    if (valor < 0) {
                        System.out.println("❌ No puede ser negativo.");
                    } else {
                        return valor;
                    }
                } catch (NumberFormatException e) {
                    System.out.println("❌ Introduce un número entero válido.");
                }
            }
        }
    
        /**
         * Lee una respuesta tipo S/N y la convierte a boolean.
         * S -> true, N -> false
         */
        private boolean leerBooleanSN(Scanner sc, String mensaje) {
            while (true) {
                System.out.print(mensaje);
                String resp = sc.nextLine().trim().toLowerCase();
    
                if (resp.equals("s") || resp.equals("si") || resp.equals("sí")) return true;
                if (resp.equals("n") || resp.equals("no")) return false;
    
                System.out.println("❌ Respuesta no válida. Escribe S o N.");
            }
        }
    }
    

    3) ControlFlota.java (main + menú)

    
    
    
    
    
    import java.util.Scanner;
    
    /**
     * Controlador principal.
     *
     * Conceptos que se trabajan:
     * - Menú por consola repetitivo (do-while)
     * - switch para ejecutar opciones
     * - Reutilización de Scanner y validación de enteros
     */
    public class ControlFlota {
    
        public static void main(String[] args) {
    
            Scanner sc = new Scanner(System.in);
            Flota flota = new Flota();
    
            // Naves iniciales opcionales (ambiente The Expanse)
            flota.agregarNave(new Nave("Rocinante", "Cinturon", 24, false));
            flota.agregarNave(new Nave("Donnager", "Marte", 60, true));
            flota.agregarNave(new Nave("Agatha King", "Tierra", 40, true));
    
            int opcion;
    
            do {
                mostrarMenu();
                opcion = leerEnteroSeguro(sc);
    
                switch (opcion) {
    
                    case 1:
                        // Crear nave desde teclado
                        flota.crearNaveDesdeTeclado(sc);
                        break;
    
                    case 2:
                        // Crear nave desde el main (valores fijos)
                        Nave n = new Nave("Nauvoo", "Cinturon", 80, false);
                        flota.agregarNave(n);
                        System.out.println("Nave creada desde main y añadida: " + n);
                        break;
    
                    case 3:
                        flota.listarTodas();
                        break;
    
                    case 4:
                        flota.listarNavesParaReparar();
                        break;
    
                    case 5:
                        System.out.println("Número total de naves: " + flota.getNumeroNaves());
                        break;
    
                    case 6:
                        System.out.println("Misiles totales en la flota: " + flota.getTotalMisiles());
                        break;
    
                    case 7:
                        System.out.print("Introduce la facción (Tierra/Marte/Cinturon): ");
                        String fac = sc.nextLine().trim();
                        flota.listarPorFaccion(fac);
                        break;
    
                    case 8:
                        System.out.print("Introduce la facción (Tierra/Marte/Cinturon): ");
                        String fac2 = sc.nextLine().trim();
                        int num = flota.contarPorFaccion(fac2);
                        System.out.println("Número de naves de la facción " + fac2 + ": " + num);
                        break;
    
                    case 0:
                        System.out.println("Saliendo del sistema de control de flota...");
                        break;
    
                    default:
                        System.out.println("Opción no válida.");
                }
    
                System.out.println(); // línea en blanco para separar “vueltas” del menú
    
            } while (opcion != 0);
    
            sc.close();
        }
    
        // -------------------------
        // Menú
        // -------------------------
        private static void mostrarMenu() {
            System.out.println("=== CONTROL DE FLOTA - GUERRA DEL SISTEMA SOLAR ===");
            System.out.println("1. Añadir nave (datos por teclado)");
            System.out.println("2. Añadir nave (creada en el main)");
            System.out.println("3. Listar todas las naves");
            System.out.println("4. Listar naves que necesitan reparación");
            System.out.println("5. Mostrar número total de naves");
            System.out.println("6. Mostrar número total de misiles");
            System.out.println("7. Listar naves por facción");
            System.out.println("8. Contar naves por facción");
            System.out.println("0. Salir");
            System.out.print("Elige una opción: ");
        }
    
        /**
         * Lee un entero de forma segura usando nextLine() + parseInt.
         * Ventaja: evita problemas típicos de Scanner con nextInt() y saltos de línea.
         */
        private static int leerEnteroSeguro(Scanner sc) {
            while (true) {
                try {
                    return Integer.parseInt(sc.nextLine().trim());
                } catch (NumberFormatException e) {
                    System.out.print("Introduce un número válido: ");
                }
            }
        }
    }
    

  • 2.1 – Librerías en Python

    2.1 – Librerías en Python

    ¿Qué es una librería en Python?

    Una librería (o “biblioteca”) es código que alguien ya escribió para resolver un problema común: hacer peticiones web, leer PDFs, crear gráficos, trabajar con fechas, etc.

    • Python estándar: viene “de serie” (por ejemplo json, os, math, datetime).
    • Librerías externas: se instalan aparte (por ejemplo requests, pandas, flask, numpy).

    Regla mental útil:

    • Si lo importas y no lo instalas, normalmente es estándar.
    • Si lo importas y te da error, probablemente hay que instalarlo.

    ¿Qué significa import?

    Cuando haces:

    
    
    
    
    
    import requests
    

    Estás diciendo: “Python, carga ese paquete para que pueda usar sus funciones”.

    También puedes importar cosas concretas:

    
    
    
    
    
    from datetime import datetime
    

    O ponerle un alias (muy común):

    
    
    
    
    
    import pandas as pd
    

    ¿Dónde se instalan librerías?

    En Python, las librerías se instalan en “un Python concreto”, que puede ser:

    1. Python del sistema (global).
    2. Un entorno virtual (recomendado para clase/proyectos).
    3. Una instalación específica (por ejemplo, un Python dentro de VS Code, conda, etc.).

    La confusión típica del alumnado:

    “He instalado requests pero sigue dando error”
    Casi siempre es porque instalaron en un Python y ejecutan con otro.


    Gestores de paquetes: pip

    pip es el instalador estándar de paquetes Python.

    Comandos básicos:

    
    
    
    
    
    pip --version
    python3 -m pip --version
    

    Instalar una librería:

    
    
    
    
    
    python3 -m pip install requests
    

    Actualizar una librería:

    
    
    
    
    
    python3 -m pip install --upgrade requests
    

    Ver lo instalado:

    
    
    
    
    
    python3 -m pip list
    

    Ver información de un paquete:

    
    
    
    
    
    python3 -m pip show requests
    

    La forma “pro” para clase: entornos virtuales (venv)

    Esto evita romper el sistema y hace que cada proyecto tenga sus librerías.

    Crear entorno virtual

    En la carpeta del proyecto:

    
    
    
    
    
    python3 -m venv venv
    

    Activarlo

    Linux/Mac:

    
    
    
    
    
    source venv/bin/activate
    

    Windows (PowerShell):

    
    
    
    
    
    venv\Scripts\Activate.ps1
    

    Windows (CMD):

    
    
    
    
    
    venv\Scripts\activate.bat
    

    Cuando está activo, normalmente verás (venv) al inicio de la terminal.

    Instalar dentro del entorno

    
    
    
    
    
    python -m pip install requests
    

    5.4 Salir del entorno

    
    
    
    
    
    deactivate
    

    Cómo saber si algo es estándar o externo

    Ejemplos:

    • Estándar:
    
    
    
    
    
    import json
    import os
    import datetime
    
    • Externas (requieren pip):
    
    
    
    
    
    import requests
    import pandas
    import flask
    

    Buenas prácticas al trabajar con librerías

    Fijar dependencias: requirements.txt

    Generar lista de dependencias del entorno:

    
    
    
    
    
    python -m pip freeze > requirements.txt
    

    Instalar dependencias en otro equipo:

    
    
    
    
    
    python -m pip install -r requirements.txt
    

    Esto es oro puro para que los proyectos “funcionen igual” en todas las máquinas.

    Leer documentación y “ejemplos mínimos”

    La documentación oficial suele tener:

    • instalación
    • ejemplos pequeños
    • parámetros importantes
    • errores comunes

    Ejemplo completo con requests (GET)

    Vamos a hacer una petición HTTP a una API pública de ejemplo y procesar JSON.

    Instalar requests

    Si estás en venv, mejor.

    
    
    
    
    
    python -m pip install requests
    

    Script: peticion_get.py

    
    
    
    
    
    import requests
    
    URL = "https://httpbin.org/get"
    
    def main():
        try:
            # timeout: evita que el programa se quede colgado si el servidor no responde
            response = requests.get(URL, timeout=10)
    
            # Lanza excepción si el status code es 4xx/5xx
            response.raise_for_status()
    
            # httpbin devuelve JSON
            data = response.json()
    
            print("✅ Status:", response.status_code)
            print("✅ Tu IP según el servidor:", data.get("origin"))
            print("✅ Headers enviados (ejemplo):")
            headers = data.get("headers", {})
            print("   User-Agent:", headers.get("User-Agent"))
    
        except requests.exceptions.Timeout:
            print("⏳ Error: timeout (el servidor tardó demasiado en responder).")
        except requests.exceptions.HTTPError as e:
            print("🚫 Error HTTP:", e)
        except requests.exceptions.RequestException as e:
            # Cubre: problemas de red, DNS, conexión, etc.
            print("🌐 Error de red:", e)
        except ValueError:
            # Si .json() falla porque la respuesta no era JSON
            print("🧩 Error: la respuesta no era JSON válido.")
    
    if __name__ == "__main__":
        main()
    

    Ejecutarlo

    
    
    
    
    
    python peticion_get.py
    

    Qué deberían observar:

    • status_code (200 si ok)
    • origin (la IP “vista” por el servidor)
    • headers (cabeceras HTTP)

    Ejemplo con parámetros (GET con params)

    params construye la query ?clave=valor.

    
    
    
    
    
    import requests
    
    URL = "https://httpbin.org/get"
    
    params = {
        "busqueda": "python",
        "pagina": 1
    }
    
    r = requests.get(URL, params=params, timeout=10)
    print("URL final:", r.url)
    print("Respuesta JSON:", r.json().get("args"))
    

    Ejemplo POST (enviar datos)

    Enviar JSON

    
    
    
    
    
    import requests
    
    URL = "https://httpbin.org/post"
    
    payload = {
        "usuario": "alumno01",
        "rol": "tester"
    }
    
    r = requests.post(URL, json=payload, timeout=10)
    r.raise_for_status()
    
    data = r.json()
    print("Enviado:", data.get("json"))
    

    Enviar formulario (application/x-www-form-urlencoded)

    
    
    
    
    
    import requests
    
    URL = "https://httpbin.org/post"
    
    form_data = {
        "email": "alumno@ejemplo.com",
        "password": "1234"
    }
    
    r = requests.post(URL, data=form_data, timeout=10)
    print(r.json().get("form"))
    

    Cabeceras y autenticación básica

    Cabeceras (headers)

    
    
    
    
    
    import requests
    
    URL = "https://httpbin.org/headers"
    
    headers = {
        "User-Agent": "ClasePython/1.0",
        "X-Profesor": "Antonio"
    }
    
    r = requests.get(URL, headers=headers, timeout=10)
    print(r.json())
    

    Auth básica (solo ejemplo didáctico)

    
    
    
    
    
    import requests
    
    URL = "https://httpbin.org/basic-auth/user/pass"
    r = requests.get(URL, auth=("user", "pass"), timeout=10)
    print(r.status_code, r.json())
    

    Errores típicos (y cómo cazarlos rápido)

    “ModuleNotFoundError: No module named ‘requests’”

    • No está instalado en ese Python.
    • Solución:
    
    
    
    
    
    python -m pip install requests
    python -c "import requests; print(requests.__version__)"
    

    “Funciona en terminal pero no en VS Code”

    • VS Code está usando otro intérprete.
    • Solución: seleccionar el intérprete del venv en VS Code (Python: Select Interpreter).

    “Se queda colgado”

    • Falta timeout.
    • Solución: siempre pon timeout=... en peticiones.