<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Giovani Fouz</title>
    <description>The latest articles on DEV Community by Giovani Fouz (@gfouz).</description>
    <link>https://dev.to/gfouz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F893736%2F6ca75795-4154-4233-887b-fd6f5cb23bf7.jpg</url>
      <title>DEV Community: Giovani Fouz</title>
      <link>https://dev.to/gfouz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gfouz"/>
    <language>en</language>
    <item>
      <title>🚀 WebVirt: Carga tu SPA en Android WebView con solo 3 líneas de código</title>
      <dc:creator>Giovani Fouz</dc:creator>
      <pubDate>Fri, 24 Apr 2026 05:16:55 +0000</pubDate>
      <link>https://dev.to/gfouz/webvirt-carga-tu-spa-en-android-webview-con-solo-3-lineas-de-codigo-5j7</link>
      <guid>https://dev.to/gfouz/webvirt-carga-tu-spa-en-android-webview-con-solo-3-lineas-de-codigo-5j7</guid>
      <description>&lt;p&gt;La primera vez que intenté cargar una SPA de React en un WebView pensé que sería trivial. No lo fue. Terminé escribiendo más de 150 líneas solo para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;servir archivos desde &lt;code&gt;assets&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;interceptar requests manualmente&lt;/li&gt;
&lt;li&gt;arreglar rutas de React Router&lt;/li&gt;
&lt;li&gt;y evitar errores 404 en producción&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Después de repetir ese proceso varias veces… decidí simplificarlo. Así nació &lt;strong&gt;WebVirt&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 El problema
&lt;/h2&gt;

&lt;p&gt;Cargar una SPA (React, Vue, Angular, Svelte) dentro de un &lt;code&gt;WebView&lt;/code&gt; en Android implica:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;WebViewAssetLoader&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;shouldInterceptRequest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;manejo manual de rutas&lt;/li&gt;
&lt;li&gt;configuración de headers y MIME types&lt;/li&gt;
&lt;li&gt;cache&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No es difícil… pero sí repetitivo, verboso y propenso a errores.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ La solución
&lt;/h2&gt;

&lt;p&gt;Con WebVirt, todo se reduce a esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;WebVirt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"miapp.local"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webView&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eso es todo.&lt;/p&gt;

&lt;p&gt;Tu WebView ya puede cargar una SPA completa desde assets sin configuración adicional.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✨ ¿Qué hace WebVirt?
&lt;/h3&gt;

&lt;p&gt;WebVirt actúa como un servidor web virtual dentro de tu APK.&lt;/p&gt;

&lt;p&gt;Intercepta las peticiones del WebView y sirve los archivos directamente desde assets, resolviendo automáticamente los problemas más comunes.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔁 SPA routing automático
&lt;/h3&gt;

&lt;p&gt;Si usas React Router (o similar), no necesitas configuración extra.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/dashboard&lt;/code&gt; → WebVirt sirve &lt;code&gt;index.html&lt;/code&gt; → tu router toma el control&lt;/p&gt;

&lt;h3&gt;
  
  
  💾 Caché inteligente
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;HTML → no cacheado (para reflejar cambios)&lt;/li&gt;
&lt;li&gt;JS/CSS → cacheado agresivamente (tipo CDN)&lt;/li&gt;
&lt;li&gt;Otros archivos → streaming directo&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔒 Seguridad básica integrada
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Prevención de directory traversal (&lt;code&gt;../&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Validación de rutas&lt;/li&gt;
&lt;li&gt;Headers seguros por defecto&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📁 MIME types listos
&lt;/h3&gt;

&lt;p&gt;Soporte para HTML, JS, CSS, JSON, imágenes, fuentes, WASM y más.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧪 Ejemplo real
&lt;/h3&gt;

&lt;p&gt;Supongamos que tienes un build de React (Vite, CRA, etc.):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/src/main/assets/
├── index.html
└── assets/
    ├── index.js
    └── index.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Solo haces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;webView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loadUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://miapp.local/"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¡Y listo!&lt;/p&gt;

&lt;p&gt;✅ React Router funciona&lt;br&gt;
✅ No hay 404 en rutas internas&lt;br&gt;
✅ No necesitas lógica extra&lt;/p&gt;
&lt;h3&gt;
  
  
  🧠 ¿Cómo funciona?
&lt;/h3&gt;

&lt;p&gt;A alto nivel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WebView → intercept request → WebVirt → assets → response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Detecta si la URL pertenece a tu host virtual.&lt;/li&gt;
&lt;li&gt;Resuelve si es archivo o ruta SPA.&lt;/li&gt;
&lt;li&gt;Sirve desde memoria o desde assets.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sin magia, solo encapsulación de lo que normalmente harías a mano.&lt;/p&gt;

&lt;h3&gt;
  
  
  🤔 ¿Por qué usarlo?
&lt;/h3&gt;

&lt;p&gt;Porque evita repetir lo mismo en cada proyecto:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;menos código boilerplate&lt;/li&gt;
&lt;li&gt;menos errores en routing&lt;/li&gt;
&lt;li&gt;mejor experiencia de desarrollo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No reemplaza las herramientas existentes,&lt;br&gt;
simplemente las abstrae en una API más simple.&lt;/p&gt;

&lt;h3&gt;
  
  
  🚀 Uso rápido en tu MainActivity
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;WebVirt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"miapp.local"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webView&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;webView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loadUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://miapp.local/"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔮 Próximamente
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Publicación en Maven Central / JitPack&lt;/li&gt;
&lt;li&gt;Kotlin DSL&lt;/li&gt;
&lt;li&gt;LRU cache configurable&lt;/li&gt;
&lt;li&gt;Hooks para personalización&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📦 Código y documentación
&lt;/h3&gt;

&lt;p&gt;Estoy preparando el repo público con README completo y ejemplos.&lt;/p&gt;

&lt;p&gt;Si te interesa el proyecto o quieres probarlo antes:&lt;/p&gt;

&lt;p&gt;👉 Déjame un comentario&lt;br&gt;
👉 o sígueme para actualizaciones&lt;/p&gt;

&lt;h3&gt;
  
  
  🎯 Conclusión
&lt;/h3&gt;

&lt;p&gt;Cargar una SPA en un WebView no debería tomar 150 líneas.&lt;/p&gt;

&lt;p&gt;Con WebVirt:&lt;/p&gt;

&lt;p&gt;✅ es simple&lt;br&gt;
✅ es rápido&lt;br&gt;
✅ funciona&lt;/p&gt;

&lt;p&gt;¿Te ha pasado lo mismo con WebView?&lt;br&gt;
Me interesa saber cómo lo estás resolviendo tú 👇&lt;/p&gt;

</description>
      <category>android</category>
      <category>mobile</category>
      <category>showdev</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Tu WebView no necesita un servidor HTTP. Necesita un Virtual Host.</title>
      <dc:creator>Giovani Fouz</dc:creator>
      <pubDate>Sun, 19 Apr 2026 09:01:38 +0000</pubDate>
      <link>https://dev.to/gfouz/tu-webview-no-necesita-un-servidor-http-necesita-un-virtual-host-3jca</link>
      <guid>https://dev.to/gfouz/tu-webview-no-necesita-un-servidor-http-necesita-un-virtual-host-3jca</guid>
      <description>&lt;h3&gt;
  
  
  Cómo un patrón de los años 90 resolvió uno de los problemas más frustrantes del desarrollo móvil moderno
&lt;/h3&gt;




&lt;p&gt;Hay una idea en ingeniería de software que reaparece una y otra vez, con décadas de distancia y en plataformas completamente distintas. Una idea tan elegante que la industria la redescubre cada cierto tiempo, la viste con nueva ropa, y la presenta como si fuera nueva.&lt;/p&gt;

&lt;p&gt;Esta es la historia de esa idea. Y de cómo terminó viviendo dentro de una app Android.&lt;/p&gt;




&lt;h2&gt;
  
  
  El problema que nadie quiere admitir
&lt;/h2&gt;

&lt;p&gt;Construir una app móvil con React, Vue o cualquier framework web moderno es tentador. Tienes un equipo que ya sabe web, una base de código compartida, y la promesa de "escribe una vez, corre en todas partes."&lt;/p&gt;

&lt;p&gt;Hasta que llega el momento de cargar tu app en Android sin conexión a internet.&lt;/p&gt;

&lt;p&gt;Android no tiene un servidor local. WebView no sabe hablar con tu carpeta &lt;code&gt;assets/&lt;/code&gt; como si fuera un dominio real. Y React Router — el corazón de la navegación en casi toda SPA moderna — necesita que las rutas como &lt;code&gt;/dashboard&lt;/code&gt; o &lt;code&gt;/perfil/123&lt;/code&gt; devuelvan siempre el mismo &lt;code&gt;index.html&lt;/code&gt;, sin importar qué tan profunda sea la URL.&lt;/p&gt;

&lt;p&gt;Sin eso, tu app se rompe. El usuario navega, presiona atrás, recarga — y ve una pantalla en blanco o un error 404 que no debería existir.&lt;/p&gt;

&lt;p&gt;La solución obvia sería levantar un servidor HTTP local. Pero eso consume batería, requiere permisos, complica el ciclo de vida de la app, y abre vectores de seguridad innecesarios. No es la respuesta correcta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;La respuesta correcta tiene 30 años de historia detrás.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  1991: Cuando los servidores aprendieron a mentir (bien)
&lt;/h2&gt;

&lt;p&gt;En los primeros días de la web, cada URL correspondía a un archivo físico en el disco del servidor. &lt;code&gt;/pagina.html&lt;/code&gt; era literalmente un archivo llamado &lt;code&gt;pagina.html&lt;/code&gt;. Simple, predecible, rígido.&lt;/p&gt;

&lt;p&gt;El problema llegó cuando los sitios crecieron. Un servidor físico, múltiples dominios. ¿Cómo diferenciaba el servidor a cuál de ellos le hablaba el visitante?&lt;/p&gt;

&lt;p&gt;La respuesta fue el &lt;strong&gt;Virtual Hosting&lt;/strong&gt;: la capacidad de un solo servidor de hacerse pasar por muchos, respondiendo diferente según el dominio que el cliente pedía. Apache HTTP Server lo popularizó a mediados de los 90. Un servidor físico podía alojar &lt;code&gt;empresa-a.com&lt;/code&gt;, &lt;code&gt;empresa-b.com&lt;/code&gt; y &lt;code&gt;empresa-c.com&lt;/code&gt; simultáneamente, cada uno con su propio espacio de archivos, sus propias reglas, su propia identidad.&lt;/p&gt;

&lt;p&gt;Era, en esencia, enseñarle a un servidor a interceptar una petición y decidir: &lt;em&gt;¿quién eres tú y qué te mereces recibir?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Nginx lo refinó. Los CDNs lo escalaron a millones de dominios. Y el patrón quedó grabado en el ADN de la infraestructura web moderna.&lt;/p&gt;




&lt;h2&gt;
  
  
  2010: Las SPAs rompen todo (de nuevo)
&lt;/h2&gt;

&lt;p&gt;Cuando llegaron las Single Page Applications, el Virtual Hosting tuvo que evolucionar.&lt;/p&gt;

&lt;p&gt;Una SPA tiene una sola entrada: &lt;code&gt;index.html&lt;/code&gt;. Todo lo demás — rutas, vistas, estados — es JavaScript puro que corre en el navegador. El servidor no sabe nada de &lt;code&gt;/dashboard&lt;/code&gt; o &lt;code&gt;/usuario/perfil&lt;/code&gt;. Cuando alguien recarga esa URL, el servidor busca un archivo llamado &lt;code&gt;dashboard&lt;/code&gt; en el disco. No existe. 404.&lt;/p&gt;

&lt;p&gt;La solución fue tan simple como poderosa: &lt;strong&gt;el fallback a index.html&lt;/strong&gt;. Si el servidor no encuentra el archivo estático solicitado, en lugar de responder con un error, devuelve siempre &lt;code&gt;index.html&lt;/code&gt;. React Router toma el control desde ahí y reconstruye la vista correcta.&lt;/p&gt;

&lt;p&gt;En Nginx, son dos líneas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="n"&gt;/index.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;En ASP.NET Core, Microsoft lo formalizó como middleware oficial con MapFallbackToFile("index.html"). El patrón tenía nombre, documentación, y respaldo institucional.&lt;/p&gt;

&lt;p&gt;Pero todo eso asume que tienes un servidor. ¿Qué pasa cuando no lo tienes?&lt;/p&gt;



&lt;p&gt;2024: El mismo patrón, sin servidor&lt;/p&gt;

&lt;p&gt;Android tiene un mecanismo poco conocido pero extraordinariamente poderoso: shouldInterceptRequest. Cada vez que el WebView está a punto de hacer una petición de red, se detiene y pregunta: ¿alguien quiere manejar esto antes que yo?&lt;/p&gt;

&lt;p&gt;La mayoría de los desarrolladores lo ignora. Algunos lo usan para bloquear anuncios o inyectar headers. Pero hay una tercera posibilidad: usarlo para construir un servidor virtual completo que nunca hace una petición de red real.&lt;/p&gt;

&lt;p&gt;Eso es exactamente lo que hace VirtualHostManager.&lt;/p&gt;

&lt;p&gt;Cuando el WebView intenta cargar &lt;a href="https://app.gfouz.com/assets/main.js" rel="noopener noreferrer"&gt;https://app.gfouz.com/assets/main.js&lt;/a&gt;, la clase intercepta esa petición antes de que salga al mundo. Busca el archivo en la carpeta assets/ del APK. Lo sirve directamente, con el MIME type correcto, con los headers de caché apropiados, sin tocar internet.&lt;/p&gt;

&lt;p&gt;Y cuando el WebView pide &lt;a href="https://app.gfouz.com/dashboard" rel="noopener noreferrer"&gt;https://app.gfouz.com/dashboard&lt;/a&gt; — una ruta de React Router que no existe como archivo — la clase reconoce que no tiene extensión, asume que es una ruta SPA, y devuelve index.html. React Router hace el resto.&lt;/p&gt;

&lt;p&gt;El servidor está dentro de la app. El dominio es ficticio. Las peticiones nunca salen del dispositivo. Y React Router nunca se entera de la diferencia.&lt;/p&gt;



&lt;p&gt;Por qué esto importa más de lo que parece&lt;/p&gt;

&lt;p&gt;La mayoría de soluciones para este problema siguen uno de dos caminos: usar file:// (que rompe CORS y tiene restricciones de seguridad severas) o levantar un servidor HTTP local con librerías como NanoHTTPD (que consume recursos y complica el ciclo de vida de la app).&lt;/p&gt;

&lt;p&gt;VirtualHostManager toma un tercer camino: habitar la infraestructura existente del WebView en lugar de luchar contra ella o rodearla.&lt;/p&gt;

&lt;p&gt;El resultado es una clase que:&lt;/p&gt;

&lt;p&gt;· No abre puertos de red.&lt;br&gt;
· No requiere permisos adicionales.&lt;br&gt;
· Cachea solo lo que vale cachear (index.html, que se pide en cada navegación).&lt;br&gt;
· Transmite archivos grandes como streams, sin cargarlos completos en RAM.&lt;br&gt;
· Valida rutas para prevenir path traversal attacks.&lt;br&gt;
· Soporta 25 tipos de archivo con sus MIME types correctos.&lt;br&gt;
· Funciona en Android 4.1 en adelante.&lt;/p&gt;

&lt;p&gt;Y hace todo eso en menos de 200 líneas de Java.&lt;/p&gt;



&lt;p&gt;El patrón que no envejece&lt;/p&gt;

&lt;p&gt;Lo fascinante de esta historia no es la clase en sí. Es que el problema — ¿cómo sirvo contenido estático con inteligencia? — ha tenido exactamente la misma solución en cada era de la computación:&lt;/p&gt;

&lt;p&gt;1995 → Apache Virtual Hosting&lt;br&gt;
2005 → Nginx try_files&lt;br&gt;
2016 → ASP.NET Core MapFallbackToFile&lt;br&gt;
2024 → Android shouldInterceptRequest + SPA fallback&lt;/p&gt;

&lt;p&gt;El contexto cambia. El hardware cambia. Los frameworks cambian. El patrón permanece.&lt;/p&gt;

&lt;p&gt;Eso, en ingeniería de software, es la señal más confiable de que algo es fundamentalmente correcto.&lt;/p&gt;

&lt;p&gt;VirtualHostManager es parte de FouzStack — una colección de soluciones de ingeniería para desarrollo móvil con tecnologías web.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://github.com/gfouz" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F82347049%3Fv%3D4%3Fs%3D400" height="300" class="m-0" width="300"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://github.com/gfouz" rel="noopener noreferrer" class="c-link"&gt;
            gfouz (Giovani Fouz) · GitHub
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Welcome,  I'm excited to share my journey,
skills, and projects with you. Dive in, explore
my projects, and get to know the developer behind
the screen. - gfouz
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.githubassets.com%2Ffavicons%2Ffavicon.svg" width="32" height="32"&gt;
          github.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>android</category>
      <category>architecture</category>
      <category>mobile</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Android Virtual Host and Fake Server</title>
      <dc:creator>Giovani Fouz</dc:creator>
      <pubDate>Tue, 14 Apr 2026 20:29:30 +0000</pubDate>
      <link>https://dev.to/gfouz/android-virtual-host-and-fake-server-3i9f</link>
      <guid>https://dev.to/gfouz/android-virtual-host-and-fake-server-3i9f</guid>
      <description>&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🚀 Virtual Host para Android: Mi réplica nativa del SetVirtualHostNameToFolderMapping de Microsoft WebView2... ¡pero para WebView de Android!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Durante algún tiempo observé una característica elegante de &lt;strong&gt;WebView2 en .NET&lt;/strong&gt;: &lt;code&gt;SetVirtualHostNameToFolderMapping&lt;/code&gt;. Te permite mapear un hostname virtual (como &lt;code&gt;https://miapp.local/&lt;/code&gt;) directamente a una carpeta local, sirviendo archivos estáticos de forma limpia, segura y con soporte perfecto para &lt;strong&gt;Single Page Applications (SPA)&lt;/strong&gt; como React, Svelte, Vue o Angular.&lt;/p&gt;

&lt;p&gt;En Android, la historia siempre ha sido más complicada. La mayoría de soluciones recurren a trucos, copiar assets a archivos internos, servidores locales embebidos (como &lt;code&gt;react-native-static-server&lt;/code&gt;) o frameworks completos que añaden capas de abstracción.&lt;/p&gt;

&lt;p&gt;Hasta ahora.&lt;/p&gt;

&lt;p&gt;Presento &lt;strong&gt;VirtualHostManager&lt;/strong&gt;: mi implementación propia, ligera y optimizada en Java/Kotlin para Android. Una clase con &lt;strong&gt;responsabilidad única&lt;/strong&gt; que transforma tu WebView en un mini-servidor virtual inteligente, inspirada directamente en la solución de Microsoft pero adaptada al ecosistema Android.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué hace exactamente?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Sirve todos tus assets estáticos desde la carpeta &lt;code&gt;assets/&lt;/code&gt; (o un subdirectorio).&lt;/li&gt;
&lt;li&gt;Maneja automáticamente el &lt;strong&gt;fallback a index.html&lt;/strong&gt; para rutas de React Router, Vue Router, etc. (cualquier ruta sin extensión se trata como SPA).&lt;/li&gt;
&lt;li&gt;Soporta dominio virtual seguro (&lt;code&gt;https://tudominio.local/&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Optimizada para bajo consumo de RAM: solo cachea &lt;code&gt;index.html&lt;/code&gt; (el archivo más solicitado), el resto se sirve con &lt;code&gt;InputStream&lt;/code&gt; directo sin cargar todo en memoria.&lt;/li&gt;
&lt;li&gt;Manejo seguro de paths (evita &lt;code&gt;../&lt;/code&gt; y accesos no deseados).&lt;/li&gt;
&lt;li&gt;Headers inteligentes de caché (immutable para JS/CSS/imágenes).&lt;/li&gt;
&lt;li&gt;Compatible con versiones antiguas de Android.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aquí el corazón de la clase (código completo en los comentarios o en el repo si lo publico):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Ejemplo de uso súper simple&lt;/span&gt;
&lt;span class="nc"&gt;VirtualHostManager&lt;/span&gt; &lt;span class="n"&gt;vhm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;VirtualHostManager&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"miapp.local"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"dist/"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;webView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setWebViewClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebViewClient&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;WebResourceResponse&lt;/span&gt; &lt;span class="nf"&gt;shouldInterceptRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WebView&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;WebResourceRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vhm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;shouldIntercept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUrl&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;vhm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;serveStaticAsset&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUrl&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;shouldInterceptRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;webView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loadUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vhm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getVirtualBaseUrl&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"index.html"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ¿Es esto una innovación a nivel de sistemas y arquitectura?
&lt;/h3&gt;

&lt;p&gt;No, no es una innovación&lt;br&gt;
disruptiva a nivel de sistemas o arquitectura, pero sí es una &lt;strong&gt;buena solución y mejora de calidad&lt;/strong&gt; sobre las soluciones típicas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Algunas ventajas:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Portabilidad de conceptos maduros de escritorio a móvil&lt;/strong&gt; — Llevamos una feature potente de WebView2 (.NET) de Microsoft al mundo Android de forma limpia y nativa, sin depender de bibliotecas pesadas ni servidores embebidos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Arquitectura minimalista y eficiente&lt;/strong&gt; — En lugar de lanzar un servidor HTTP completo (con overhead de hilos, sockets y consumo de batería), usamos el mecanismo nativo de &lt;code&gt;shouldInterceptRequest&lt;/code&gt; del WebView. Es más directo, ligero y respeta el ciclo de vida de la app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimización consciente de recursos móviles&lt;/strong&gt; — El diseño prioriza bajo uso de RAM y CPU, algo crítico en dispositivos Android de gama media/baja. El cacheo lazy y thread-safe de solo &lt;code&gt;index.html&lt;/code&gt; es un detalle pequeño pero poderoso para SPAs con navegación frecuente.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No es "reinventar la rueda". Es &lt;strong&gt;traer la rueda correcta al vehículo correcto&lt;/strong&gt;, con mejoras específicas para el entorno móvil.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ventajas frente a soluciones modernas existentes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Vs. React Native + WebView&lt;/strong&gt; (o &lt;code&gt;react-native-webview&lt;/code&gt;):&lt;br&gt;&lt;br&gt;
React Native obliga a un puente JS → Native, añade complejidad de ecosistema y tamaño de APK. Con VirtualHostManager cargas tu SPA React/Vue directamente en un WebView nativo puro. Menos capas = mejor rendimiento, menor tamaño y mantenimiento más simple si ya tienes el frontend web.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Vs. Capacitor / Ionic / Cordova&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Estos frameworks son geniales para acceso a APIs nativas, pero introducen su propio runtime, plugins y bridge. Si tu app es principalmente una SPA web bien hecha, VirtualHostManager te da control total sin el overhead. Quieres cámara o notificaciones? Añades solo los permisos y llamadas nativas que necesites, sin arrastrar todo el framework.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Vs. WebViewAssetLoader (oficial de AndroidX)&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Es buena, pero más básica. No maneja automáticamente el fallback SPA de forma tan elegante, ni domina el concepto de "virtual host" con dominio personalizado. Mi implementación es más cercana a la experiencia de WebView2.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Vs. servidores locales embebidos (NanoHTTPD, etc.)&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Mucho más pesado en memoria y batería. Mi solución es interceptación directa: cero sockets, cero hilos extras.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Resultado&lt;/strong&gt;: una app más ligera, más rápida al arrancar, con mejor ahorro de batería y que se siente como una experiencia web premium dentro de un contenedor nativo.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Para quién es ideal?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Desarrolladores que tienen una &lt;strong&gt;SPA moderna&lt;/strong&gt; (React, Vue, Svelte, etc.) y quieren empaquetarla como app Android con mínima fricción.&lt;/li&gt;
&lt;li&gt;Equipos que buscan &lt;strong&gt;máximo rendimiento&lt;/strong&gt; y control fino sin adoptar un framework completo.&lt;/li&gt;
&lt;li&gt;Quienes valoran la simplicidad y la inspiración cross-platform (de .NET a Android).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esta clase es open-source en espíritu: la comparto porque creo que la comunidad Android merece herramientas más elegantes para servir SPAs locales, teniendo muy en cuenta que las aplicaciones web son cada vez más sofisticadas y de alta tecnología. &lt;/p&gt;

&lt;p&gt;¿Qué opinas?&lt;br&gt;&lt;br&gt;
¿Te ha pasado que luchas con WebView + SPA y terminas añadiendo capas innecesarias?&lt;br&gt;&lt;br&gt;
¿Crees que vale la pena priorizar esta simplicidad sobre frameworks más "todo en uno"?&lt;/p&gt;

&lt;p&gt;Me encantaría leer tus experiencias en comentarios. Si te sirve, ¡úsala, mejórala y compártela!&lt;/p&gt;

&lt;h1&gt;
  
  
  Android #WebView #React #typescript  #tailwindcss  #SPA  #MobileDevelopment #Architecture #DotNet #Kotlin #Java
&lt;/h1&gt;

</description>
      <category>android</category>
      <category>mobile</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Virtual Host for Android</title>
      <dc:creator>Giovani Fouz</dc:creator>
      <pubDate>Tue, 14 Apr 2026 04:37:16 +0000</pubDate>
      <link>https://dev.to/gfouz/virtual-host-for-android-17na</link>
      <guid>https://dev.to/gfouz/virtual-host-for-android-17na</guid>
      <description>&lt;p&gt;Implementando el Patrón UseSpa de ASP.NET Core en Android WebView: Una Alternativa Ligera a Cordova para SPAs Offline&lt;/p&gt;

&lt;p&gt;Cómo construí un enrutador SPA eficiente para apps React que se ejecutan completamente desde los assets de Android, sin servidor HTTP y con consumo mínimo de batería y de RAM.&lt;/p&gt;




&lt;p&gt;El Problema: El Enrutamiento SPA se Rompe en Android WebView&lt;/p&gt;

&lt;p&gt;Si alguna vez has intentado empaquetar una app React o Vue dentro de un WebView de Android usando file:///android_asset/index.html, te has topado con este muro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;net::ERR_FILE_NOT_FOUND
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La página de inicio carga perfectamente. Pero cuando el usuario navega a /inventario y refresca la página (o recibe un enlace profundo), el WebView intenta buscar el archivo físico /inventario dentro de la carpeta assets. No existe. La app se rompe.&lt;/p&gt;

&lt;p&gt;Las soluciones tradicionales son pesadas:&lt;/p&gt;

&lt;p&gt;Solución Problema&lt;br&gt;
Cordova / Capacitor Levanta un servidor HTTP real en localhost. Funciona, pero consume batería y RAM.&lt;br&gt;
PWA con Service Workers Requiere HTTPS e internet para la primera carga. No es verdaderamente offline-first.&lt;/p&gt;

&lt;p&gt;Pero espera—Microsoft ya resolvió esto elegantemente en ASP.NET Core:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseStaticFiles&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSpa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;spa&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;spa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultPage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/index.html"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este middleware sirve archivos estáticos normalmente, pero hace fallback a index.html para cualquier ruta que no tenga extensión de archivo. React Router toma el control a partir de ahí.&lt;/p&gt;

&lt;p&gt;Entonces me pregunté: "¿Por qué Android no tiene algo así?"&lt;/p&gt;




&lt;p&gt;La Solución: VirtualHostManager&lt;/p&gt;

&lt;p&gt;Desarrollé una clase Java ligera que replica el comportamiento de UseSpa de ASP.NET completamente dentro de la capa de interceptación de peticiones del WebView. Sin servidor HTTP local. Sin Cordova. Android SDK puro o Java sin dependencias ni librerías externas.&lt;/p&gt;

&lt;p&gt;El Corazón de la idea&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * Determina si una ruta solicitada es una ruta de React Router.
 * Lógica: Si no tiene extensión de archivo, es una ruta SPA.
 */&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isReactRouterRoute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;assetPath&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assetPath&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;assetPath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;lastDot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assetPath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lastIndexOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'.'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lastDot&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Sin extensión = ruta SPA&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta simple validación es lo que permite que /inventario, /reportes o /configuracion no devuelvan 404, sino que entreguen index.html para que React Router maneje la navegación.&lt;/p&gt;

&lt;p&gt;Configuración del WebView&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;VirtualHostManager&lt;/span&gt; &lt;span class="n"&gt;vhm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;VirtualHostManager&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"app.local"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"www"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;webView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setWebViewClient&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebViewClient&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;WebResourceResponse&lt;/span&gt; &lt;span class="nf"&gt;shouldInterceptRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WebView&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;WebResourceRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUrl&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vhm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;shouldIntercept&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;vhm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;serveStaticAsset&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;shouldInterceptRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;webView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loadUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vhm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getVirtualBaseUrl&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// https://app.local/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;El Código Completo (Fragmentos Clave)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Interceptación y Fallback al Index
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;WebResourceResponse&lt;/span&gt; &lt;span class="nf"&gt;serveStaticAsset&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;relativePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urlToAssetPath&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;fullAssetPath&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// 🧠 Aquí está la innovación: detección de rutas SPA&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isReactRouterRoute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relativePath&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;relativePath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fullAssetPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;indexAssetPath&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Fallback a index.html&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fullAssetPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assetSubfolder&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;relativePath&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Servir desde assets con MIME types y headers de caché&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;create404Response&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Cacheo Thread-Safe de index.html
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;indexHtmlCache&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Double-checked locking para evitar bloqueos innecesarios en lecturas concurrentes&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullAssetPath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indexAssetPath&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indexHtmlCache&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;synchronized&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indexHtmlCache&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;indexHtmlCache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;loadAssetBytes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullAssetPath&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;dataStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ByteArrayInputStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indexHtmlCache&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Validación de Seguridad contra Path Traversal
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;validatePath&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;".."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\\"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startsWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SecurityException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Path inválido: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Limpieza de URLs con Fragmentos y Query Params
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;urlToAssetPath&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;replace&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;replace&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;replace&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;virtualHost&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;replace&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;virtualHost&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"?"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\\?"&lt;/span&gt;&lt;span class="o"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="o"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Optimizaciones que Marcan la Diferencia&lt;/p&gt;

&lt;p&gt;Característica Implementación Beneficio&lt;br&gt;
Cacheo de index.html volatile + double-checked locking Acceso concurrente sin bloqueos&lt;br&gt;
Cero sobrecarga de RAM para otros assets InputStream directo, sin byte[] Memoria mínima en dispositivos viejos&lt;br&gt;
Headers de caché inmutables max-age=31536000 para assets con hash El WebView no re-descarga archivos&lt;br&gt;
Protección contra Path Traversal Bloqueo de ../ y rutas absolutas Seguridad en apps offline&lt;br&gt;
Soporte para subcarpetas assetSubfolder configurable Compatible con npm run build sin cambios&lt;/p&gt;




&lt;p&gt;Comparativa: VirtualHostManager vs. Soluciones Existentes&lt;/p&gt;

&lt;p&gt;Métrica Cordova/Capacitor WebView + file://  VirtualHostManager&lt;br&gt;
Soporte SPA Routing ✅ Sí ❌ Roto ✅ Sí&lt;br&gt;
Requiere Servidor HTTP ✅ Sí (localhost) ❌ No ❌ No&lt;br&gt;
Consumo de Batería Alto Bajo Mínimo&lt;br&gt;
Consumo de RAM ~40-60 MB ~10 MB ~8 MB&lt;br&gt;
Deep Linking ✅ Sí ❌ No ✅ Sí&lt;br&gt;
Hot Updates ❌ No ❌ No ✅ Sí (reemplazar assets)&lt;br&gt;
Tiempo de inicio Lento (espera al servidor) Instantáneo Instantáneo&lt;/p&gt;




&lt;p&gt;Caso de Uso Real: App de Inventarios en Cuba&lt;/p&gt;

&lt;p&gt;Esta solución está actualmente en producción en una app de control de inventarios para pequeños negocios en Cuba, donde:&lt;/p&gt;

&lt;p&gt;· El internet es caro e inestable.&lt;br&gt;
· Los dispositivos tienen RAM y batería limitadas.&lt;br&gt;
· El trabajo por turnos requiere traspaso de datos offline vía exportación  de archivos.&lt;/p&gt;

&lt;p&gt;La app funciona completamente offline, sincroniza mediante archivos exportados, y genera reportes PDF—todo desde un único WebView con persistencia de datos utilizando a IndexDB. &lt;/p&gt;




&lt;p&gt;Código Fuente Completo&lt;br&gt;
En fin quiero compartir este pensamiento:&lt;/p&gt;

&lt;p&gt;No necesitas Cordova para tener una SPA funcional en Android. A veces, una clase Java de 150 líneas es todo lo que necesitas para que React Router funcione como si estuviera en un servidor real.&lt;/p&gt;

&lt;p&gt;Microsoft lo hizo bien con UseSpa. Ahora Android también lo tiene, (VirtualHostManager) una clase de 150 líneas en Java. &lt;/p&gt;




&lt;p&gt;¿Preguntas? ¿Ideas? &lt;/p&gt;

&lt;p&gt;Déjamelas en los comentarios. Si estás construyendo algo similar para entornos offline-first en Latinoamérica, me encantaría saber de tu proyecto.&lt;/p&gt;




&lt;p&gt;Giovani Fouz&lt;br&gt;
Desarrollador de Software. No deberíamos aferrarnos a ciertas tecnologías donde radica nuestra zona de comodidad  sino explorar nuevas alternativas, pero no termino sin mencionar: ¡ Wow vaya éxito el de React o Typescript o Tailwindcss !  ¡ Que grandiosas herramientas!&lt;br&gt;
Cuba, 2026&lt;/p&gt;




</description>
      <category>android</category>
      <category>mobile</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Comprendiendo el uso del Asterisco (`*`) y Doble Asterisco (`**`) en Python</title>
      <dc:creator>Giovani Fouz</dc:creator>
      <pubDate>Sat, 09 Nov 2024 11:15:03 +0000</pubDate>
      <link>https://dev.to/gfouz/comprendiendo-el-uso-del-asterisco-y-doble-asterisco-en-python-2i4e</link>
      <guid>https://dev.to/gfouz/comprendiendo-el-uso-del-asterisco-y-doble-asterisco-en-python-2i4e</guid>
      <description>&lt;p&gt;Cuando trabajamos en Python, a menudo nos encontramos con situaciones en las que necesitamos que nuestras funciones sean flexibles y capaces de manejar diferentes tipos y cantidades de argumentos. Para facilitar esto, Python ofrece dos operadores muy útiles: el asterisco simple (&lt;code&gt;*&lt;/code&gt;) y el doble asterisco (&lt;code&gt;**&lt;/code&gt;). En este post, exploraremos en detalle su funcionamiento, así como su aplicación en funciones, clases y estructuras de datos como listas y diccionarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué son las estructuras de datos en Python?
&lt;/h2&gt;

&lt;p&gt;Antes de entrar en el uso del asterisco, es importante entender qué son las estructuras de datos. En Python, las estructuras de datos son formas de organizar y almacenar datos en el programa. Las más comunes son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Listas&lt;/strong&gt;: Colecciones ordenadas que permiten elementos duplicados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tuplas&lt;/strong&gt;: Similares a las listas, pero son inmutables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diccionarios&lt;/strong&gt;: Colecciones no ordenadas de pares clave-valor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Estas estructuras son fundamentales para manejar datos en Python y son el contexto donde los operadores &lt;code&gt;*&lt;/code&gt; y &lt;code&gt;**&lt;/code&gt; se vuelven particularmente interesantes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usos del Asterisco Simple (&lt;code&gt;*&lt;/code&gt;)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Funciones con Argumentos Variables
&lt;/h3&gt;

&lt;p&gt;El asterisco simple se utiliza principalmente en funciones para permitir que acepten un número variable de argumentos posicionales. Esto significa que puedes pasarle cualquier cantidad de argumentos y todos serán tratados como una tupla dentro de la función.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Esto imprime: 1 2 3 4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Desempaquetado de Listas o Tuplas
También puedes usar el asterisco simple para desempaquetar elementos de una lista o tupla al pasar argumentos a una función.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Esto imprime: 1 2 3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este uso del asterisco puede ser muy conveniente cuando tienes una lista de elementos y quieres pasarlos como argumentos a otra función.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usos del Doble Asterisco (&lt;code&gt;**&lt;/code&gt;)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Funciones con Argumentos de Palabra Clave
El doble asterisco se utiliza para permitir que una función acepte un número variable de argumentos de palabra clave (nombre-valor). Dentro de la función, estos argumentos se almacenan en un diccionario.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Salida:
# name: Alice
# age: 30
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Desempaquetado de Diccionarios
Al igual que el asterisco para listas y tuplas, puedes usar el doble asterisco para desempaquetar pares clave-valor desde un diccionario al llamar a una función.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;age&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Osea es lo mismo que: func(name="Alice", age=30)
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usos Avanzados de * y ** en Clases
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;

&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# (1, 2)
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# {'a': 3, 'b': 4}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En Herencia&lt;br&gt;
Puedes utilizar *args y **kwargs para pasar argumentos al constructor de la clase base, lo que permite que la clase derivada extienda el comportamiento del constructor de la clase base.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Derived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Llama al constructor de Base
&lt;/span&gt;        &lt;span class="c1"&gt;# Puedes hacer algo adicional con args y kwargs aquí
&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Derived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combinaciones de simple y doble asterisco:&lt;br&gt;
A veces, puede ser útil combinar tanto los argumentos posicionales como los de palabra clave en tus funciones para permitir un manejo completo de los datos de entrada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;mixed_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;mixed_args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;#Salida:
&lt;/span&gt;
&lt;span class="c1"&gt;# 1 2
# (3, 4)
# {'x': 5, 'y': 6}
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://docs.python.org/3/tutorial/controlflow.html#defining-functions" rel="noopener noreferrer"&gt;Documentación Oficial de Python sobre Funciones&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.py4e.com" rel="noopener noreferrer"&gt;Python para Todos - Curso Gratuito&lt;/a&gt;&lt;br&gt;
&lt;a href="https://realpython.com/python-unpacking/" rel="noopener noreferrer"&gt;Real Python - Unpacking in Python&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.w3schools.com/python/python_functions.asp" rel="noopener noreferrer"&gt;W3Schools - Python Functions (Defining Functions)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resumen:
&lt;/h2&gt;

&lt;p&gt;args es útil para recibir un número variable de argumentos posicionales, mientras que kwargs es útil para recibir un número variable de argumentos de palabra clave.&lt;br&gt;
Puedes usar simple y doble asterisco para desempaquetar listas/tuplas y diccionarios, respectivamente, al llamar funciones.&lt;br&gt;
Ambos operadores pueden mejorar la flexibilidad y reutilización de tu código, permitiendo funciones que manejan diferentes tipos de entradas de manera eficiente.&lt;br&gt;
Recursos Útiles&lt;/p&gt;

</description>
    </item>
    <item>
      <title>React query, hook personalizado.</title>
      <dc:creator>Giovani Fouz</dc:creator>
      <pubDate>Sat, 09 Nov 2024 08:02:56 +0000</pubDate>
      <link>https://dev.to/gfouz/react-query-hook-personalizado-3a5m</link>
      <guid>https://dev.to/gfouz/react-query-hook-personalizado-3a5m</guid>
      <description>&lt;p&gt;En aplicaciones de React, es común necesitar acceder a datos de una API externa. Tradicionalmente, muchos desarrolladores utilizan métodos nativos de javascript como fetch dentro de los componentes, lo que puede llevar a problemas de administración del estado y a un manejo complicado de efectos secundarios (side effects). Aquí es donde React Query entra en juego.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es React Query?
&lt;/h3&gt;

&lt;p&gt;React Query es una biblioteca destinada a simplificar las operaciones de obtención y manejo de datos en React. Proporciona potentes funciones para:&lt;/p&gt;

&lt;p&gt;Efectuar solicitudes de datos de una API.&lt;br&gt;
Almacenar y sincronizar el estado de la UI con los datos.&lt;br&gt;
Realizar refetching automáticamente y gestionar cachés.&lt;br&gt;
Nuestro Hook Personalizado&lt;/p&gt;

&lt;p&gt;A continuación, veamos nuestro hook personalizado, useCustomQuery:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GenericObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;QueryFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GenericObject&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useCustomQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;queryFunction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;QueryFunction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isPending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
    &lt;span class="nx"&gt;GenericObject&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;GenericObject&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;queryFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isPending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Desglose del Hook
&lt;/h2&gt;

&lt;h3&gt;
  
  
  GenericObject y QueryFunction:
&lt;/h3&gt;

&lt;p&gt;Definimos tipos genéricos que facilitan el trabajo con objetos y funciones que realizan fetching de datos. Esto asegura que nuestro código pueda adaptarse a diferentes estructuras de datos que puedan regresar las APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  useQuery:
&lt;/h3&gt;

&lt;p&gt;Usamos el hook useQuery de React Query, que maneja automáticamente el estado de nuestras solicitudes. Proporciona propiedades útiles para manejar la carga de datos, errores y refetching.        &lt;/p&gt;

&lt;p&gt;Esto mejora la calidad del código y reduce bugs.&lt;br&gt;
Interfaces Genéricas: Utilizando interfaces genéricas, podemos definir estructuras de datos que se adaptan a diferentes situaciones. Esto hace que el código sea más reutilizable y fácil de mantener.&lt;br&gt;
Mejor Documentación: El uso de TypeScript como una herramienta de documentación proporcionada por los tipos mejora la comprensión de cómo se deben usar las funciones y qué tipo de datos se esperan.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enlaces Útiles
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;React Query&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documentación oficial: &lt;a href="https://react-query.tanstack.com/" rel="noopener noreferrer"&gt;TanStack Query Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Guía de inicio rápido: &lt;a href="https://react-query.tanstack.com/overview" rel="noopener noreferrer"&gt;Getting Started with React Query&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documentación oficial: &lt;a href="https://www.typescriptlang.org/docs/" rel="noopener noreferrer"&gt;TypeScript Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Guía de TypeScript para React: &lt;a href="https://react-typescript-cheatsheet.netlify.app/" rel="noopener noreferrer"&gt;Using TypeScript with React&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;GitHub de React Query&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repositorio oficial: &lt;a href="https://github.com/TanStack/query" rel="noopener noreferrer"&gt;TanStack Query (React Query) GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ejemplos y Tutoriales&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tutorial de RapidAPI sobre React Query: &lt;a href="https://rapidapi.com/blog/react-query/" rel="noopener noreferrer"&gt;Getting Started with React Query&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Artículo sobre los beneficios de utilizar React Query: &lt;a href="https://blog.logrocket.com/why-you-should-use-react-query-in-your-next-react-app/" rel="noopener noreferrer"&gt;Benefits of Using React Query&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Conclusión
&lt;/h3&gt;

&lt;p&gt;Integrar un hook personalizado junto con React Query y TypeScript en tus aplicaciones React transforma la forma en que gestionas las solicitudes de datos. No sólo mejora la experiencia de desarrollo al reducir la carga de lógica de manejo de estado, sino que también enriquece la robustez y facilidad de mantenimiento de tu código.&lt;br&gt;
Espero que encuentren útil este enfoque y les animo a probarlo en sus propios proyectos. ¡Feliz codificación!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Errores Comunes de Pylint. Guía Práctica</title>
      <dc:creator>Giovani Fouz</dc:creator>
      <pubDate>Mon, 27 May 2024 09:10:20 +0000</pubDate>
      <link>https://dev.to/gfouz/errores-comunes-de-pylint-guia-practica-2ko</link>
      <guid>https://dev.to/gfouz/errores-comunes-de-pylint-guia-practica-2ko</guid>
      <description>&lt;p&gt;Pylint es una herramienta de análisis estático de código que se utiliza para encontrar errores y mejorar la calidad del código Python. Sin embargo, enfrentarse a los errores que reporta puede ser desalentador, especialmente para los desarrolladores novatos. Aquí exploramos algunos de los errores más comunes que lanza Pylint, cómo resolverlos y cómo podemos beneficiarnos de estas correcciones para escribir un código más limpio y eficiente.&lt;/p&gt;

&lt;p&gt;1- C0103: Variable name "x" doesn't conform to snake_case naming style&lt;br&gt;
Error:&lt;br&gt;
Este error se produce cuando el nombre de una variable no sigue la convención de nombres en Python, que es usar snake_case.&lt;/p&gt;

&lt;p&gt;Ejemplo de código que lanza el error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;userName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;John Doe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Solución:&lt;br&gt;
Renombrar la variable para que siga la convención snake_case.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;John Doe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- E1101: Instance of 'class' has no 'member' member&lt;br&gt;
Error:&lt;br&gt;
Pylint no puede encontrar el atributo especificado en la instancia de la clase. Esto suele ocurrir cuando se intenta acceder a un atributo que no existe.&lt;/p&gt;

&lt;p&gt;Ejemplo de código que lanza el error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;

&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Solución:&lt;br&gt;
Asegurarse de que el atributo exista en la clase.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;

&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3- R0913: Too many arguments (6/5)&lt;br&gt;
Error:&lt;br&gt;
Esta advertencia surge cuando una función o método tiene demasiados parámetros, lo cual puede hacer que el código sea difícil de mantener y leer.&lt;/p&gt;

&lt;p&gt;Ejemplo de código que lanza el error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Solución:&lt;br&gt;
Reducir el número de parámetros, por ejemplo, utilizando un diccionario o una clase.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="n"&gt;user_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;johndoe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;12345&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;john@example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;John&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Doe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4- W0611: Unused 'import'&lt;br&gt;
Error:&lt;br&gt;
Este error aparece cuando hay una importación en el código que no se utiliza, lo que puede añadir desorden innecesario.&lt;/p&gt;

&lt;p&gt;Ejemplo de código que lanza el error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Solución:&lt;br&gt;
Eliminar las importaciones no utilizadas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5- C0301: Line too long (82/80)&lt;br&gt;
Error:&lt;br&gt;
Este error se produce cuando una línea de código supera la longitud máxima recomendada de 80 caracteres.&lt;/p&gt;

&lt;p&gt;Ejemplo de código que lanza el error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. Welcome to the platform. We hope you have a great experience here!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Solución:&lt;br&gt;
Dividir la línea larga en varias líneas más cortas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. Welcome to the platform. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;We hope you have a great experience here!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conclusión:&lt;/p&gt;

&lt;p&gt;Abordar y resolver los errores que Pylint destaca puede parecer un desafío, pero es un paso crucial hacia la mejora continua y la profesionalización de nuestro código. Cada corrección que hacemos nos acerca a un código más limpio, más eficiente y más fácil de mantener. Acepta los mensajes de Pylint como oportunidades de aprendizaje y crecimiento profesional.&lt;/p&gt;

&lt;p&gt;Para más detalles, puedes consultar la documentación oficial de Pylint que proporciona una guía exhaustiva sobre cómo interpretar y resolver los mensajes de error.&lt;/p&gt;

&lt;p&gt;Mantén la motivación y recuerda: escribir un buen código no es solo una habilidad técnica, sino también un arte que se perfecciona con práctica y perseverancia. ¡Sigue adelante y convierte cada error en un aprendizaje!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>¿Morirá React como jQuery?</title>
      <dc:creator>Giovani Fouz</dc:creator>
      <pubDate>Sun, 26 May 2024 21:35:15 +0000</pubDate>
      <link>https://dev.to/gfouz/morira-react-como-jquery-13bl</link>
      <guid>https://dev.to/gfouz/morira-react-como-jquery-13bl</guid>
      <description>&lt;p&gt;En el dinámico mundo del desarrollo web, las tecnologías van y vienen. jQuery, una vez la herramienta preferida para la manipulación del DOM y la gestión de eventos, ha sido en gran medida eclipsada por la evolución del lenguaje JavaScript y la aparición de frameworks más modernos. Esto plantea una cuestión pertinente: ¿podría React, la popular biblioteca de JavaScript para construir interfaces de usuario, eventualmente sufrir el mismo destino? Analicemos esta pregunta en detalle.&lt;/p&gt;

&lt;h2&gt;
  
  
  La Historia de jQuery
&lt;/h2&gt;

&lt;p&gt;Para comprender si React podría seguir el mismo camino que jQuery, es esencial entender primero cómo jQuery alcanzó su apogeo y posterior declive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ascenso de jQuery:
&lt;/h2&gt;

&lt;p&gt;Simplificación del DOM: En sus inicios, la manipulación del DOM y la gestión de eventos eran tareas tediosas y llenas de inconsistencias entre navegadores. jQuery ofreció una API sencilla y uniforme que facilitó estas tareas.&lt;br&gt;
Compatibilidad Cross-Browser: jQuery resolvía muchos problemas de compatibilidad entre navegadores, una de las mayores dificultades para los desarrolladores web de la época.&lt;br&gt;
Extensibilidad y Plugins: jQuery ofrecía un sistema de plugins robusto, permitiendo a los desarrolladores añadir funcionalidades adicionales con facilidad.&lt;/p&gt;

&lt;h2&gt;
  
  
  Declive de jQuery:
&lt;/h2&gt;

&lt;p&gt;Evolución del JavaScript Nativo: Con la llegada de ECMAScript 5 y, posteriormente, ECMAScript 6 (ES6), muchas de las funcionalidades que jQuery proporcionaba se integraron directamente en el lenguaje.&lt;br&gt;
Nuevos Frameworks y Bibliotecas: Frameworks como Angular, React y Vue ofrecieron soluciones más completas y modernas para la creación de aplicaciones web, reduciendo la necesidad de jQuery.&lt;br&gt;
Mejora de los Navegadores: Los navegadores modernizaron sus API, reduciendo las inconsistencias y, por ende, la necesidad de una biblioteca como jQuery para gestionar estas diferencias.&lt;br&gt;
La Situación Actual de React&lt;br&gt;
React, lanzado por Facebook en 2013, se ha convertido en una de las bibliotecas más populares para la construcción de interfaces de usuario, gracias a varias características clave:&lt;/p&gt;

&lt;p&gt;Componentización: React introdujo el concepto de componentes reutilizables, facilitando la gestión de interfaces complejas.&lt;br&gt;
Virtual DOM: React utiliza un DOM virtual para minimizar las operaciones costosas en el DOM real, mejorando el rendimiento.&lt;/p&gt;

&lt;p&gt;Ecosistema y Herramientas: React cuenta con un ecosistema robusto, incluyendo herramientas como Redux para la gestión del estado, y Next.js para el renderizado del lado del servidor.&lt;br&gt;
Adopción y Soporte Empresarial: Grandes empresas han adoptado React, lo que garantiza su soporte continuo y evolución.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Podría React Volverse Obsoleto?
&lt;/h2&gt;

&lt;p&gt;Aunque React goza de una popularidad y uso extensivo en la actualidad, no es invulnerable a los cambios y avances tecnológicos. Aquí algunos factores que podrían influir en su futuro:&lt;/p&gt;

&lt;h2&gt;
  
  
  Emergencia de Nuevas Tecnologías:
&lt;/h2&gt;

&lt;p&gt;Tecnologías más recientes podrían surgir con paradigmas de desarrollo más eficientes. Por ejemplo, Svelte es un framework que compila el código a JavaScript puro, eliminando la necesidad de un virtual DOM.&lt;br&gt;
Evolución del Lenguaje y Estándares Web:&lt;/p&gt;

&lt;p&gt;Si el lenguaje JavaScript y los estándares web continúan evolucionando, podrían integrar de forma nativa muchas de las funcionalidades que actualmente proporcionan bibliotecas como React. Esto podría hacer que los desarrolladores prefieran soluciones nativas más ligeras.&lt;br&gt;
Competencia de Otros Frameworks:&lt;/p&gt;

&lt;p&gt;Frameworks competidores como Vue.js y Angular siguen evolucionando y ofreciendo características únicas que podrían atraer a los desarrolladores. También, frameworks como Solid.js y Qwik, que promueven un rendimiento y eficiencia superiores, podrían ganar terreno.&lt;br&gt;
Saturación del Ecosistema:&lt;/p&gt;

&lt;p&gt;La complejidad creciente del ecosistema de React, con la proliferación de librerías y herramientas adicionales, podría desanimar a los nuevos desarrolladores y conducirlos a buscar alternativas más simples.&lt;/p&gt;

&lt;p&gt;Conclusión&lt;/p&gt;

&lt;p&gt;En resumen, mientras que es difícil predecir con certeza el futuro de cualquier tecnología, la trayectoria de jQuery ofrece lecciones valiosas. React, con su fuerte adopción y apoyo comunitario, está bien posicionado para permanecer relevante en el futuro cercano. Sin embargo, la continua evolución del desarrollo web significa que siempre habrá nuevas tecnologías y paradigmas que podrían desplazar a las herramientas actuales. La clave para la longevidad de React residirá en su capacidad para adaptarse e innovar frente a estos cambios constantes.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>¿Morirá React como jQuery?</title>
      <dc:creator>Giovani Fouz</dc:creator>
      <pubDate>Sun, 26 May 2024 21:34:58 +0000</pubDate>
      <link>https://dev.to/gfouz/morira-react-como-jquery-31ce</link>
      <guid>https://dev.to/gfouz/morira-react-como-jquery-31ce</guid>
      <description>&lt;p&gt;En el dinámico mundo del desarrollo web, las tecnologías van y vienen. jQuery, una vez la herramienta preferida para la manipulación del DOM y la gestión de eventos, ha sido en gran medida eclipsada por la evolución del lenguaje JavaScript y la aparición de frameworks más modernos. Esto plantea una cuestión pertinente: ¿podría React, la popular biblioteca de JavaScript para construir interfaces de usuario, eventualmente sufrir el mismo destino? Analicemos esta pregunta en detalle.&lt;/p&gt;

&lt;h2&gt;
  
  
  La Historia de jQuery
&lt;/h2&gt;

&lt;p&gt;Para comprender si React podría seguir el mismo camino que jQuery, es esencial entender primero cómo jQuery alcanzó su apogeo y posterior declive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ascenso de jQuery:
&lt;/h2&gt;

&lt;p&gt;Simplificación del DOM: En sus inicios, la manipulación del DOM y la gestión de eventos eran tareas tediosas y llenas de inconsistencias entre navegadores. jQuery ofreció una API sencilla y uniforme que facilitó estas tareas.&lt;br&gt;
Compatibilidad Cross-Browser: jQuery resolvía muchos problemas de compatibilidad entre navegadores, una de las mayores dificultades para los desarrolladores web de la época.&lt;br&gt;
Extensibilidad y Plugins: jQuery ofrecía un sistema de plugins robusto, permitiendo a los desarrolladores añadir funcionalidades adicionales con facilidad.&lt;/p&gt;

&lt;h2&gt;
  
  
  Declive de jQuery:
&lt;/h2&gt;

&lt;p&gt;Evolución del JavaScript Nativo: Con la llegada de ECMAScript 5 y, posteriormente, ECMAScript 6 (ES6), muchas de las funcionalidades que jQuery proporcionaba se integraron directamente en el lenguaje.&lt;br&gt;
Nuevos Frameworks y Bibliotecas: Frameworks como Angular, React y Vue ofrecieron soluciones más completas y modernas para la creación de aplicaciones web, reduciendo la necesidad de jQuery.&lt;br&gt;
Mejora de los Navegadores: Los navegadores modernizaron sus API, reduciendo las inconsistencias y, por ende, la necesidad de una biblioteca como jQuery para gestionar estas diferencias.&lt;br&gt;
La Situación Actual de React&lt;br&gt;
React, lanzado por Facebook en 2013, se ha convertido en una de las bibliotecas más populares para la construcción de interfaces de usuario, gracias a varias características clave:&lt;/p&gt;

&lt;p&gt;Componentización: React introdujo el concepto de componentes reutilizables, facilitando la gestión de interfaces complejas.&lt;br&gt;
Virtual DOM: React utiliza un DOM virtual para minimizar las operaciones costosas en el DOM real, mejorando el rendimiento.&lt;/p&gt;

&lt;p&gt;Ecosistema y Herramientas: React cuenta con un ecosistema robusto, incluyendo herramientas como Redux para la gestión del estado, y Next.js para el renderizado del lado del servidor.&lt;br&gt;
Adopción y Soporte Empresarial: Grandes empresas han adoptado React, lo que garantiza su soporte continuo y evolución.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Podría React Volverse Obsoleto?
&lt;/h2&gt;

&lt;p&gt;Aunque React goza de una popularidad y uso extensivo en la actualidad, no es invulnerable a los cambios y avances tecnológicos. Aquí algunos factores que podrían influir en su futuro:&lt;/p&gt;

&lt;h2&gt;
  
  
  Emergencia de Nuevas Tecnologías:
&lt;/h2&gt;

&lt;p&gt;Tecnologías más recientes podrían surgir con paradigmas de desarrollo más eficientes. Por ejemplo, Svelte es un framework que compila el código a JavaScript puro, eliminando la necesidad de un virtual DOM.&lt;br&gt;
Evolución del Lenguaje y Estándares Web:&lt;/p&gt;

&lt;p&gt;Si el lenguaje JavaScript y los estándares web continúan evolucionando, podrían integrar de forma nativa muchas de las funcionalidades que actualmente proporcionan bibliotecas como React. Esto podría hacer que los desarrolladores prefieran soluciones nativas más ligeras.&lt;br&gt;
Competencia de Otros Frameworks:&lt;/p&gt;

&lt;p&gt;Frameworks competidores como Vue.js y Angular siguen evolucionando y ofreciendo características únicas que podrían atraer a los desarrolladores. También, frameworks como Solid.js y Qwik, que promueven un rendimiento y eficiencia superiores, podrían ganar terreno.&lt;br&gt;
Saturación del Ecosistema:&lt;/p&gt;

&lt;p&gt;La complejidad creciente del ecosistema de React, con la proliferación de librerías y herramientas adicionales, podría desanimar a los nuevos desarrolladores y conducirlos a buscar alternativas más simples.&lt;/p&gt;

&lt;p&gt;Conclusión&lt;/p&gt;

&lt;p&gt;En resumen, mientras que es difícil predecir con certeza el futuro de cualquier tecnología, la trayectoria de jQuery ofrece lecciones valiosas. React, con su fuerte adopción y apoyo comunitario, está bien posicionado para permanecer relevante en el futuro cercano. Sin embargo, la continua evolución del desarrollo web significa que siempre habrá nuevas tecnologías y paradigmas que podrían desplazar a las herramientas actuales. La clave para la longevidad de React residirá en su capacidad para adaptarse e innovar frente a estos cambios constantes.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Why are algorithms called algorithms?</title>
      <dc:creator>Giovani Fouz</dc:creator>
      <pubDate>Sun, 26 May 2024 06:39:09 +0000</pubDate>
      <link>https://dev.to/gfouz/why-are-algorithms-called-algorithms-1292</link>
      <guid>https://dev.to/gfouz/why-are-algorithms-called-algorithms-1292</guid>
      <description>&lt;p&gt;The origin of the word dates back more than a thousand years ago. And the invention of the concept is attributed to a Persian polymath and scientist considered “the grandfather of computing.”&lt;/p&gt;

&lt;p&gt;Algorithms have become an integral part of our lives. From social media apps to Netflix, they are programs that learn our preferences and prioritize the content we are shown. Google Maps and artificial intelligence are nothing without them. But where does the word come from?&lt;/p&gt;

&lt;p&gt;More than 1,000 years before the internet and smartphone apps, Persian scientist and polymath Muhammad ibn Mūsā al-Khwārizmī invented the concept of an algorithm. In fact, the word itself comes from the Latinized version of his name, algorithmi. And, as you might suspect, it is also related to algebra.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lost in time
&lt;/h2&gt;

&lt;p&gt;Al-Khwārizmī lived between 780 and 850, during the Islamic Golden Age. He is considered the “father of algebra” and, for some, the “grandfather of computing.” However, few details are known about his life. Many of his original works in Arabic have been lost to time. He is believed to have been born in the Khorasmian region, south of the Aral Sea, in modern-day Uzbekistan. He lived during the Abbasid Caliphate, a time of notable scientific progress in the Islamic Empire.&lt;/p&gt;

&lt;p&gt;We know that he made important contributions to mathematics, geography, astronomy and trigonometry. He corrected Ptolemy 's classic cartography book , Geography , to make the world map more accurate. He also made calculations to track the movement of the Sun, Moon, and planets. In addition, he wrote about trigonometric functions and created the first table of tangents.&lt;/p&gt;

&lt;p&gt;For all his qualities, Al-Khwārizmī served as a scholar in the House of Wisdom (Bayt al-Hikmah) in Baghdad. In this intellectual center, scholars translated knowledge from around the world into Arabic and synthesized it to achieve significant advances in various disciplines.&lt;/p&gt;

&lt;p&gt;A devoted mathematician&lt;br&gt;
Al-Khwārizmī was a religious man. His scientific writings began with dedications to Allah and the Prophet Muhammad. And one of the main projects they undertook at the House of Wisdom was to develop algebra. Mathematics was, in general, a field deeply related to Islam .&lt;/p&gt;

&lt;p&gt;Around 830, the Caliph Al-Mamun encouraged Al-Khwārizmī to write a treatise on algebra, Al-Jabr (or Compendium of Calculus by Reintegration and Comparison ), which would become his most important work.&lt;/p&gt;

&lt;p&gt;By now, algebra had been around for hundreds of years, but Al-Khwārizmī was the first to write a definitive book on it. It was intended to be a practical teaching tool and its Latin translation was the basis of algebra manuals in European universities until the 16th century.&lt;/p&gt;

&lt;h2&gt;
  
  
  Father of algebra
&lt;/h2&gt;

&lt;p&gt;In the first part of the book, he introduces the concepts and rules of this subject, as well as the methods for calculating the volumes and areas of figures. In the second, he poses real-life problems and elaborates solutions, such as inheritance cases, the division of land, and calculations for trade.&lt;/p&gt;

&lt;p&gt;Al-Khwārizmī did not use modern mathematical notation with numbers and symbols. Instead, he wrote in simple prose and used geometric diagrams: Four roots are equal to twenty, so one root is equal to five, and the square formed from it is twenty-five, or half the root is equal to ten.&lt;/p&gt;

&lt;p&gt;In modern notation we would write it like this: 4x = 20, x = 5, x2 = 25, x / 2 = 10&lt;/p&gt;

&lt;h2&gt;
  
  
  Grandfather of computing
&lt;/h2&gt;

&lt;p&gt;Al-Khwārizmī's mathematical writings introduced the Hindu-Arabic numerals to Western mathematicians: 1, 2, 3, 4, 5, 6, 7, 8, 9, 0. These symbols are important to the history of computing because they use the number zero and a base ten decimal system, the number system on which modern computer technology is based.&lt;/p&gt;

&lt;p&gt;Furthermore, Al-Khwārizmī's art of calculating mathematical problems laid the foundation for the concept of algorithm. He provided the first detailed explanations of using decimal notation to perform the four basic operations (addition, subtraction, multiplication, division) and calculating fractions.&lt;/p&gt;

&lt;p&gt;It was a more efficient calculation method than the abacus. To solve a mathematical equation, you systematically went through a sequence of steps until you found the answer. This is the underlying concept of an algorithm.&lt;/p&gt;

&lt;p&gt;Algorithm, a medieval Latin term named after Al-Khwārizmī, refers to the rules for performing arithmetic operations using the Hindu-Arabic number system. Translated into Latin, Al-Khwārizmī's book on Hindu numbers was titled Algorithmi de Numero Indorum .&lt;/p&gt;

&lt;p&gt;At the beginning of the 20th century, the word acquired its current definition and use: “Ordered and finite set of operations that allows finding the solution to a problem.” So the next time we use any digital technology – from social media to the online bank account to the Spotify app – we already know that none of this would be possible without the pioneering work of an ancient Persian polymath.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Introducción a Pydantic para Principiantes.</title>
      <dc:creator>Giovani Fouz</dc:creator>
      <pubDate>Thu, 23 May 2024 18:05:22 +0000</pubDate>
      <link>https://dev.to/gfouz/introduccion-a-pydantic-para-principiantes-b6l</link>
      <guid>https://dev.to/gfouz/introduccion-a-pydantic-para-principiantes-b6l</guid>
      <description>&lt;p&gt;Pydantic es una poderosa biblioteca en Python diseñada para la validación y gestión de datos. Es especialmente útil cuando trabajas con datos que necesitan ser validados y transformados, como datos de entrada de API o formularios. Aquí te explico cómo empezar con Pydantic de manera sencilla.&lt;/p&gt;

&lt;p&gt;¿Qué es Pydantic?&lt;br&gt;
Pydantic permite definir modelos de datos utilizando anotaciones de tipo, y automáticamente valida y transforma los datos según estas anotaciones. Esto significa que puedes asegurarte de que tus datos tienen el formato correcto antes de usarlos en tu aplicación.&lt;/p&gt;

&lt;p&gt;Instalación:&lt;br&gt;
Primero, necesitas instalar Pydantic. Puedes hacerlo usando pip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install pydantic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creación de un Modelo o Esquema:&lt;br&gt;
Un modelo en Pydantic es una clase que hereda de BaseModel. Definimos los atributos de esta clase con sus tipos, y Pydantic se encarga del resto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;span class="n"&gt;signup_ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;span class="n"&gt;friends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este ejemplo, User es un modelo con cuatro atributos:&lt;/p&gt;

&lt;p&gt;id: un entero obligatorio.&lt;br&gt;
name: una cadena de texto obligatoria.&lt;br&gt;
signup_ts: una marca de tiempo opcional.&lt;br&gt;
friends: una lista de enteros, que por defecto es una lista vacía.&lt;/p&gt;

&lt;p&gt;Validación de Datos:&lt;br&gt;
Una vez definido el modelo, podemos crear instancias del mismo y Pydantic validará automáticamente los datos proporcionados.&lt;/p&gt;

&lt;p&gt;Una vez definido el modelo, podemos crear instancias del mismo y Pydantic validará automáticamente los datos proporcionados.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;

&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;John Doe&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signup_ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;friends&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si los datos no son válidos, Pydantic generará un error.&lt;/p&gt;

&lt;p&gt;Transformación de Datos:&lt;br&gt;
Pydantic también puede transformar los datos según las anotaciones de tipo. Por ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;123&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;John Doe&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aquí, Pydantic convertirá el id de cadena de texto a entero automáticamente.&lt;/p&gt;

&lt;p&gt;Configuración Avanzada&lt;br&gt;
Pydantic ofrece muchas opciones avanzadas, como alias para nombres de campos, validaciones personalizadas, y uso con JSON.&lt;/p&gt;

&lt;p&gt;Alias&lt;br&gt;
Podemos usar alias para los campos, lo que es útil cuando los nombres de los datos de entrada no coinciden con los de nuestro modelo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;John Doe&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Integración con JSON&lt;br&gt;
Pydantic facilita trabajar con JSON, permitiendo la exportación e importación de modelos a/desde JSON.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;John Doe&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;user_json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;user_from_json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse_raw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_from_json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conclusión&lt;br&gt;
Pydantic es una herramienta poderosa para la validación y transformación de datos en Python. Facilita el trabajo con datos estructurados y ayuda a asegurar que tus datos sean correctos y consistentes. ¡Empieza a usar Pydantic en tus proyectos y simplifica la gestión de datos en tus aplicaciones!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Type hints are a powerful feature in Python</title>
      <dc:creator>Giovani Fouz</dc:creator>
      <pubDate>Mon, 20 May 2024 12:08:48 +0000</pubDate>
      <link>https://dev.to/gfouz/type-hints-are-a-powerful-feature-in-python-ii0</link>
      <guid>https://dev.to/gfouz/type-hints-are-a-powerful-feature-in-python-ii0</guid>
      <description>&lt;p&gt;Type hints are a powerful feature in Python that improve code readability, facilitate error detection, and enhance tooling support. Introduced in PEP 484, type hints allow developers to specify the expected types of variables, function parameters, and return values. While Python remains dynamically typed, these annotations provide significant benefits in terms of code quality and maintainability.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore what type hints are, why you should use them, and how to effectively integrate them into your Python projects.&lt;/p&gt;

&lt;p&gt;What are Type Hints?&lt;br&gt;
Type hints are annotations that specify the types of variables, function parameters, and return values in Python code. They do not enforce type checking at runtime but are used by static type checkers, IDEs, and other tools to provide better code analysis and assistance.&lt;/p&gt;

&lt;p&gt;Here’s a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;
&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.75&lt;/span&gt;
&lt;span class="n"&gt;is_student&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this snippet, the function greet expects a string parameter and returns a string. Additionally, we define variables with explicit types: age, height, and is_student.&lt;/p&gt;

&lt;p&gt;Why Use Type Hints?&lt;br&gt;
Improved Code Readability: Type hints make the code self-documenting by clearly indicating the expected types, making it easier to understand and maintain.&lt;br&gt;
Early Error Detection: Static type checkers like mypy, pyright, and pylint can catch type-related errors before runtime, reducing the likelihood of bugs.&lt;br&gt;
Better IDE Support: Modern IDEs use type hints for autocompletion, refactoring, and error checking, which significantly enhances the development experience.&lt;br&gt;
Enhanced Documentation: Type hints act as an implicit form of documentation, providing insights into the function’s behavior and expected inputs/outputs.&lt;br&gt;
Using Type Hints with Collections&lt;br&gt;
Python’s typing module provides several generic types for annotating collections. Here are some common examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;

&lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bob&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Charlie&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;ages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bob&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;40.7128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;74.0060&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Advanced Type Hinting&lt;br&gt;
Type hints can also handle more complex scenarios such as functions with multiple arguments, optional values, and custom types.&lt;/p&gt;

&lt;p&gt;Multiple Argument Types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Union&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Union&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optional Values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_user_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Custom Types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NewType&lt;/span&gt;

&lt;span class="n"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NewType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;UserId&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UserId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Static Type Checking Tools&lt;br&gt;
To fully leverage the power of type hints, integrating static type checkers into your development workflow is essential. Here are some popular tools:&lt;/p&gt;

&lt;p&gt;mypy: A static type checker for Python that checks type annotations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install mypy
mypy script.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;pyright: A fast type checker by Microsoft, often used with Visual Studio Code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g pyright
pyright script.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;pylint: A code analysis tool that also supports type checking.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install pylint
pylint script.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Best Practices for Using Type Hints&lt;/p&gt;

&lt;p&gt;Be Consistent: Use type hints consistently throughout your codebase to maintain readability and reliability.&lt;br&gt;
Start Small: If you're new to type hints, start by annotating new functions and gradually add annotations to existing code.&lt;br&gt;
Leverage Tooling: Use static type checkers and IDE support to catch errors early and improve code quality.&lt;br&gt;
Annotate External APIs: Always use type hints for public APIs to provide clear expectations for other developers using your code.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;br&gt;
Type hints in Python are an invaluable tool for improving code clarity, reducing errors, and enhancing the development experience. By incorporating type hints into your projects, you can create more maintainable, readable, and robust code. Start using type hints today and see the difference they can make in your Python development workflow.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
