<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Teoría · DacaCode &lt;/&gt;</title><link>https://blog.dacadev.com/tags/teor%C3%ADa/</link><description>Blog de tecnología, programación y electrónica, para compartir conocimientos, experiencias y tutoriales con este apasionante mundo.</description><generator>Hugo</generator><language>es-CO</language><copyright>Copyright © 2026 DacaDev. All rights reserved.</copyright><lastBuildDate>Thu, 30 Jul 2026 00:00:00 -0500</lastBuildDate><atom:link href="https://blog.dacadev.com/tags/teor%C3%ADa/index.xml" rel="self" type="application/rss+xml"/><image><url>https://blog.dacadev.com/images/blog-logo.png</url><title>DacaCode &lt;/&gt;</title><link>https://blog.dacadev.com/</link></image><item><title>RAG: Pipeline de Indexación con Chunking, Embeddings y FAISS</title><link>https://blog.dacadev.com/generative-ai/rag/pipeline-de-indexacion/</link><pubDate>Thu, 30 Jul 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/generative-ai/rag/pipeline-de-indexacion/</guid><dc:creator>Dacadev</dc:creator><category>IA generativa</category><description>Aprende a construir el pipeline de indexación de un RAG en Python: carga de datos, chunking, embeddings y almacenamiento en una base vectorial.</description><media:content url="https://blog.dacadev.com/images/generative-ai/rag/03-pipeline-de-indexacion/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#carga-de-datos"&gt;Carga de datos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#segmentación-en-chunks"&gt;Segmentación en chunks&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#métodos-de-chunking"&gt;Métodos de chunking&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#conversión-a-embeddings"&gt;Conversión a embeddings&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#cómo-se-mide-la-similitud"&gt;Cómo se mide la similitud&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#almacenamiento-en-una-base-de-datos-vectorial"&gt;Almacenamiento en una base de datos vectorial&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#pipeline-completo"&gt;Pipeline completo&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#verificación-rápida"&gt;Verificación rápida&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión-y-próximos-pasos"&gt;Conclusión y próximos pasos&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;En el &lt;a href="https://blog.dacadev.com/generative-ai/rag/arquitectura-de-un-rag/"



 


&gt;artículo anterior de esta serie&lt;/a&gt; vimos que el &lt;strong&gt;indexing pipeline&lt;/strong&gt; se compone de cuatro etapas: carga, fragmentación, conversión y almacenamiento. Hoy vamos a construir cada una de esas etapas con código real, usando como hilo conductor el ejemplo del &lt;a href="https://blog.dacadev.com/generative-ai/rag/que-es-un-rag/"



 


&gt;primer artículo&lt;/a&gt;: un LLM que no sabe qué equipos jugarán la semifinal del Mundial 2026 porque su conocimiento no llega hasta esa fecha.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Este es el tercer artículo de la serie &lt;strong&gt;RAGs&lt;/strong&gt;. Vamos a implementar el &lt;strong&gt;indexing pipeline&lt;/strong&gt; completo en Python: carga de datos, chunking, embeddings y una base de datos vectorial con &lt;strong&gt;FAISS&lt;/strong&gt;. El código se irá acumulando en cada sección hasta terminar en un script único, listo para usar. 🚀&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="carga-de-datos"&gt;Carga de datos&lt;/h2&gt;
&lt;p&gt;El primer paso es traer la información desde su fuente original, sin importar si esta es una página web, un PDF o una API. Aunque suena trivial, esta etapa suele resolver varios problemas antes de entregar texto limpio: conexión y autenticación con la fuente, límites de &lt;em&gt;rate limit&lt;/em&gt;, paginación y el formato en el que llegan los datos.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 S[&amp;#34;📂 Fuente&amp;#34;] --&amp;gt; C[&amp;#34;🔌 Conector&amp;lt;br/&amp;gt;conexión y auth&amp;#34;]
 C --&amp;gt; E[&amp;#34;📑 Extractor&amp;lt;br/&amp;gt;parseo de texto&amp;#34;]
 E --&amp;gt; M[&amp;#34;🏷️ Metadatos&amp;lt;br/&amp;gt;añade/actualiza&amp;#34;]
 M --&amp;gt; T[&amp;#34;🧹 Transformador&amp;lt;br/&amp;gt;limpieza y formato&amp;#34;]
 T --&amp;gt; OUT[&amp;#34;📄 Texto plano&amp;#34;]
&lt;/pre&gt;

&lt;p&gt;Para nuestro ejemplo usaremos la página de Wikipedia de la &lt;a href="https://es.wikipedia.org/wiki/Copa_Mundial_de_F%C3%BAtbol_de_2026"




 target="_blank"
 


&gt;&lt;em&gt;Copa Mundial de Fútbol de 2026&lt;/em&gt;&lt;/a&gt;. Con &lt;a href="https://python.langchain.com/"




 target="_blank"
 


&gt;LangChain&lt;/a&gt; podemos descargar el HTML de forma asíncrona y transformarlo a texto plano en pocas líneas.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Final&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_community.document_loaders&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;AsyncHtmlLoader&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_community.document_loaders.async_html&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;default_header_template&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_community.document_transformers&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Html2TextTransformer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;URL_OBJETIVO&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Final&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;https://es.wikipedia.org/wiki/Copa_Mundial_de_F%C3%BAtbol_de_2026&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;cargar_y_limpiar_documento&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;url&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;URL_OBJETIVO&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; Descarga el contenido HTML de una URL de forma asíncrona
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; y lo transforma a texto plano.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;# Wikipedia exige identificar el User-Agent en las peticiones (https://w.wiki/4wJS)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;encabezados&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;dict&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;default_header_template&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;encabezados&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;User-Agent&amp;#34;&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;DacaDev/0.0 (mi_correo@gmail.com)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;cargador_html&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;AsyncHtmlLoader&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;url&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;header_template&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e06c75"&gt;encabezados&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;documentos_html&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;cargador_html&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;load&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;transformador_html_a_texto&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Html2TextTransformer&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;documentos_texto_plano&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;transformador_html_a_texto&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;transform_documents&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;documentos_html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;documentos_texto_plano&lt;/span&gt;[&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;]&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;page_content&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Dependencias usadas en esta sección: &lt;code&gt;langchain&lt;/code&gt;, &lt;code&gt;langchain-community&lt;/code&gt;, &lt;code&gt;bs4&lt;/code&gt; y &lt;code&gt;html2text&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="segmentación-en-chunks"&gt;Segmentación en chunks&lt;/h2&gt;
&lt;p&gt;Con el texto limpio en mano, el siguiente problema es que no podemos meter un documento entero en cada consulta al LLM. Dividirlo en fragmentos —&lt;strong&gt;chunks&lt;/strong&gt;— ataca tres limitaciones que ya vimos en el &lt;a href="https://blog.dacadev.com/generative-ai/rag/que-es-un-rag/"



 


&gt;primer artículo&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Context window limitado&lt;/strong&gt;: si llenamos el contexto con un documento completo para usar solo una parte, desperdiciamos capacidad del modelo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lost in the middle&lt;/strong&gt;: en documentos largos, el modelo tiende a perder información ubicada en la mitad del texto.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Precisión de la búsqueda semántica&lt;/strong&gt;: chunks pequeños y enfocados producen coincidencias más relevantes que un documento gigante.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;El proceso de chunking sigue siempre la misma lógica, sin importar la herramienta que uses:&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 D[&amp;#34;📄 Documento&amp;lt;br/&amp;gt;cargado&amp;#34;] --&amp;gt; P1[&amp;#34;1️⃣ Dividir en&amp;lt;br/&amp;gt;unidades pequeñas&amp;#34;]
 P1 --&amp;gt; P2[&amp;#34;2️⃣ Fusionar en&amp;lt;br/&amp;gt;chunks de tamaño objetivo&amp;#34;]
 P2 --&amp;gt; P3[&amp;#34;3️⃣ Agregar overlap&amp;lt;br/&amp;gt;entre chunks&amp;#34;]
 P3 --&amp;gt; CH[(&amp;#34;🧩 Chunks&amp;#34;)]
&lt;/pre&gt;

&lt;p&gt;El &lt;strong&gt;overlap&lt;/strong&gt; (solapamiento) repite un pequeño trozo del chunk anterior al inicio del siguiente, para no cortar una idea justo en la frontera entre dos fragmentos.&lt;/p&gt;
&lt;h3 id="métodos-de-chunking"&gt;Métodos de chunking&lt;/h3&gt;
&lt;p&gt;No todos los métodos dividen el texto de la misma forma. Estos son los más comunes:&lt;/p&gt;



&lt;div class="tab" data-tab-group=""&gt;
 &lt;ul class="tab-nav" data-tab-nav&gt;
 
 &lt;li
 class="tab-nav-item active"
 data-tab="ancho-fijo" tabindex="0"&gt;
 Ancho fijo
 &lt;/li&gt;
 
 &lt;li
 class="tab-nav-item "
 data-tab="recursivo" tabindex="-1"&gt;
 Recursivo
 &lt;/li&gt;
 
 &lt;li
 class="tab-nav-item "
 data-tab="por-tokens" tabindex="-1"&gt;
 Por tokens
 &lt;/li&gt;
 
 &lt;li
 class="tab-nav-item "
 data-tab="estructural" tabindex="-1"&gt;
 Estructural
 &lt;/li&gt;
 
 &lt;/ul&gt;
 &lt;div class="tab-content" data-tab-content&gt;
 
 &lt;div
 class="tab-content-panel active"
 data-tab-panel="ancho-fijo"&gt;
 &lt;p&gt;Corta por un carácter específico (&lt;code&gt;\n&lt;/code&gt;, por ejemplo) y mide el tamaño en caracteres. Es el método más simple y predecible.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_text_splitters&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;CharacterTextSplitter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;separador&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;CharacterTextSplitter&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;separator&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#98c379"&gt;\n&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;chunk_size&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1000&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;chunk_overlap&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;200&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;fragmentos&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;separador&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;create_documents&lt;/span&gt;([&lt;span style="color:#e06c75"&gt;texto&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/div&gt;
 
 &lt;div
 class="tab-content-panel "
 data-tab-panel="recursivo"&gt;
 &lt;p&gt;Prueba una lista de separadores en orden de jerarquía (párrafos, líneas, oraciones, palabras) hasta lograr chunks del tamaño deseado. Es el método recomendado para texto genérico.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_text_splitters&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;separador&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;separators&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#98c379"&gt;\n\n&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#98c379"&gt;\n&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34; &amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;chunk_size&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1000&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;chunk_overlap&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;200&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;fragmentos&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;separador&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;create_documents&lt;/span&gt;([&lt;span style="color:#e06c75"&gt;texto&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/div&gt;
 
 &lt;div
 class="tab-content-panel "
 data-tab-panel="por-tokens"&gt;
 &lt;p&gt;Igual que el ancho fijo o el recursivo, pero mide &lt;code&gt;chunk_size&lt;/code&gt; y &lt;code&gt;chunk_overlap&lt;/code&gt; en tokens en vez de caracteres, usando el encoder de un tokenizer.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;separador&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;from_tiktoken_encoder&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;encoding_name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;cl100k_base&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;chunk_size&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;100&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;chunk_overlap&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;10&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/div&gt;
 
 &lt;div
 class="tab-content-panel "
 data-tab-panel="estructural"&gt;
 &lt;p&gt;Divide según la estructura del documento (encabezados HTML, tablas) en vez de un tamaño fijo. Útil cuando el formato original aporta información.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_text_splitters&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;HTMLSectionSplitter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;secciones&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [(&lt;span style="color:#98c379"&gt;&amp;#34;h1&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;Encabezado 1&amp;#34;&lt;/span&gt;), (&lt;span style="color:#98c379"&gt;&amp;#34;h2&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;Encabezado 2&amp;#34;&lt;/span&gt;), (&lt;span style="color:#98c379"&gt;&amp;#34;table&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;Tabla&amp;#34;&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;segmentador&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;HTMLSectionSplitter&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;secciones&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;fragmentos&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;segmentador&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;split_text&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;contenido_html&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;/div&gt;
 
 &lt;/div&gt;
&lt;/div&gt;





 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;No existe un método &amp;ldquo;correcto&amp;rdquo; universal: depende del tipo de contenido, del tamaño esperado de las consultas y del modelo de embeddings que uses. Para nuestro caso —texto genérico proveniente de Wikipedia— el splitter &lt;strong&gt;recursivo&lt;/strong&gt; es la mejor opción por defecto.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Sumamos esta etapa a nuestro flujo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_core.documents&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Document&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_text_splitters&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;dividir_texto_en_fragmentos&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;texto&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;Document&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; Divide un texto intentando mantener oraciones y párrafos completos.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;separador_recursivo&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;separators&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#98c379"&gt;\n\n&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#98c379"&gt;\n&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34; &amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;chunk_size&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1000&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;chunk_overlap&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;200&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;separador_recursivo&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;create_documents&lt;/span&gt;([&lt;span style="color:#e06c75"&gt;texto&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Dependencia añadida: &lt;code&gt;langchain-text-splitters&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="conversión-a-embeddings"&gt;Conversión a embeddings&lt;/h2&gt;
&lt;p&gt;Ya tenemos los chunks, pero un motor de búsqueda no entiende texto: entiende números. Los &lt;strong&gt;embeddings&lt;/strong&gt; son la solución — representaciones vectoriales donde textos con significado similar quedan ubicados cerca entre sí en el espacio vectorial.&lt;/p&gt;
&lt;p&gt;Con una sola dimensión apenas podemos ordenar palabras en una línea, lo que deja fuera relaciones de significado más ricas:&lt;/p&gt;




 
 
 
 &lt;div class="flex justify-center"&gt;
 &lt;img
 src="https://blog.dacadev.com/images/generative-ai/rag/03-pipeline-de-indexacion/embeddings-1d_hu_6726d71a48d96ace.webp"
 alt="Imagen guia del contenido de la página"/&gt;
 &lt;/div&gt;
 
 
 


&lt;p&gt;Al aumentar las dimensiones ganamos flexibilidad para ubicar cada palabra según su relación real con las demás:&lt;/p&gt;




 
 
 
 &lt;div class="flex justify-center"&gt;
 &lt;img
 src="https://blog.dacadev.com/images/generative-ai/rag/03-pipeline-de-indexacion/embeddings-2d_hu_50fd3deb604c414c.webp"
 alt="Imagen guia del contenido de la página"/&gt;
 &lt;/div&gt;
 
 
 


&lt;p&gt;Un &lt;strong&gt;modelo de embeddings&lt;/strong&gt; generaliza esta idea a &lt;em&gt;n&lt;/em&gt; dimensiones: convierte cada texto en un vector numérico que captura su significado.&lt;/p&gt;




 
 
 
 &lt;div class="flex justify-center"&gt;
 &lt;img
 src="https://blog.dacadev.com/images/generative-ai/rag/03-pipeline-de-indexacion/embeddings-modelo_hu_9990c60bb0e1390d.webp"
 alt="Imagen guia del contenido de la página"/&gt;
 &lt;/div&gt;
 
 
 


&lt;p&gt;Estos modelos se entrenan sobre grandes corpus de texto usando arquitecturas como Word2Vec, GloVe o BERT. Algunos de los modelos preentrenados más usados hoy:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Proveedor&lt;/th&gt;
 &lt;th&gt;Modelo&lt;/th&gt;
 &lt;th&gt;Dimensiones&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;OpenAI&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;text-embedding-3-small/large&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;1536 / 3072&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Google&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;text-embedding-004&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;hasta 768&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Voyage AI&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;voyage-large-2&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;1536&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Cohere&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;embed-multilingual-v3.0&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;1024&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Open source (HF)&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;sentence-transformers&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;varía (ej. 768)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="cómo-se-mide-la-similitud"&gt;Cómo se mide la similitud&lt;/h3&gt;
&lt;p&gt;Una vez que dos textos son vectores, ¿cómo sabemos si son &amp;ldquo;parecidos&amp;rdquo;? La métrica más usada es la &lt;strong&gt;similitud coseno&lt;/strong&gt;: el coseno del ángulo entre dos vectores. Cuanto más cercano a &lt;code&gt;1&lt;/code&gt;, más similares son; cercano a &lt;code&gt;0&lt;/code&gt; implica que no están relacionados, y cercano a &lt;code&gt;-1&lt;/code&gt; indica significados opuestos.&lt;/p&gt;




 
 
 
 &lt;div class="flex justify-center"&gt;
 &lt;img
 src="https://blog.dacadev.com/images/generative-ai/rag/03-pipeline-de-indexacion/similitud-coseno_hu_8d07583fc6c433a5.webp"
 alt="Imagen guia del contenido de la página"/&gt;
 &lt;/div&gt;
 
 
 


&lt;p&gt;Para nuestro pipeline usaremos un modelo open source de &lt;a href="https://www.sbert.net/"




 target="_blank"
 


&gt;sentence-transformers&lt;/a&gt; vía LangChain, que genera embeddings de 768 dimensiones sin depender de una API externa:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_huggingface&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;HuggingFaceEmbeddings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;crear_modelo_embeddings&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;HuggingFaceEmbeddings&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; Instancia el modelo de embeddings que convertirá cada chunk en un vector.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;HuggingFaceEmbeddings&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;model_name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;sentence-transformers/all-mpnet-base-v2&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;También podrías usar modelos privados como los de OpenAI (&lt;code&gt;OpenAIEmbeddings&lt;/code&gt;) o Voyage AI simplemente cambiando esta función; el resto del pipeline no cambia.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Dependencias añadidas: &lt;code&gt;langchain-huggingface&lt;/code&gt;, &lt;code&gt;sentence-transformers&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="almacenamiento-en-una-base-de-datos-vectorial"&gt;Almacenamiento en una base de datos vectorial&lt;/h2&gt;
&lt;p&gt;Ya tenemos vectores; ahora necesitamos guardarlos en algún lugar donde se puedan buscar por similitud de forma rápida. Ahí entran las &lt;strong&gt;bases de datos vectoriales&lt;/strong&gt;, optimizadas para indexar y consultar vectores de alta dimensión.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Categoría&lt;/th&gt;
 &lt;th&gt;Ejemplos&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Índices vectoriales&lt;/td&gt;
 &lt;td&gt;FAISS, ANNOY, ScaNN&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Bases especializadas&lt;/td&gt;
 &lt;td&gt;Pinecone, Chroma, Qdrant, Milvus, Weaviate&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Plataformas de búsqueda&lt;/td&gt;
 &lt;td&gt;Elasticsearch, OpenSearch&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;SQL con soporte vectorial&lt;/td&gt;
 &lt;td&gt;PostgreSQL (&lt;code&gt;pgvector&lt;/code&gt;), Azure SQL&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;NoSQL con soporte vectorial&lt;/td&gt;
 &lt;td&gt;MongoDB&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Para este ejemplo usaremos &lt;a href="https://faiss.ai/"




 target="_blank"
 


&gt;&lt;strong&gt;FAISS&lt;/strong&gt;&lt;/a&gt; (Facebook AI Similarity Search): una librería ligera, local y suficiente para un prototipo o un proyecto pequeño.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_community.vectorstores&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;FAISS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;construir_base_vectorial&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;fragmentos&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;Document&lt;/span&gt;], &lt;span style="color:#e06c75"&gt;modelo_embeddings&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;HuggingFaceEmbeddings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;FAISS&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; Genera el embedding de cada chunk y los indexa en una base vectorial FAISS.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;FAISS&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;from_documents&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;fragmentos&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;modelo_embeddings&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;FAISS se puede persistir en disco con &lt;code&gt;base_vectorial.save_local(ruta)&lt;/code&gt; y recuperar después con &lt;code&gt;FAISS.load_local(ruta, modelo_embeddings)&lt;/code&gt;, sin necesidad de recalcular los embeddings cada vez que arranca la aplicación.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Al elegir una base de datos vectorial para producción, más allá de FAISS, vale la pena evaluar:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Factor&lt;/th&gt;
 &lt;th&gt;Qué implica&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Precisión vs. velocidad&lt;/td&gt;
 &lt;td&gt;Índices más precisos suelen ser más lentos de consultar.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Local vs. cloud&lt;/td&gt;
 &lt;td&gt;Acceso rápido y control total vs. escalabilidad y redundancia administradas.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Costo&lt;/td&gt;
 &lt;td&gt;Autohospedado con costo de infraestructura vs. servicio administrado con costo por uso.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="pipeline-completo"&gt;Pipeline completo&lt;/h2&gt;
&lt;p&gt;Con las cuatro etapas listas, así queda el script completo: descarga la página, la limpia, la fragmenta, genera los embeddings y los indexa en FAISS.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Final&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_community.document_loaders&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;AsyncHtmlLoader&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_community.document_loaders.async_html&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;default_header_template&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_community.document_transformers&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Html2TextTransformer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_community.vectorstores&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;FAISS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_core.documents&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Document&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_huggingface&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;HuggingFaceEmbeddings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;langchain_text_splitters&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;URL_OBJETIVO&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Final&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;https://es.wikipedia.org/wiki/Copa_Mundial_de_F%C3%BAtbol_de_2026&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;RUTA_INDICE&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Final&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;indice_mundial_2026&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;cargar_y_limpiar_documento&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;url&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;URL_OBJETIVO&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; Descarga el contenido HTML de una URL de forma asíncrona
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; y lo transforma a texto plano.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;encabezados&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;dict&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;default_header_template&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;encabezados&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;User-Agent&amp;#34;&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;DacaDev/0.0 (mi_correo@gmail.com)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;cargador_html&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;AsyncHtmlLoader&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;url&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;header_template&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e06c75"&gt;encabezados&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;documentos_html&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;cargador_html&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;load&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;transformador_html_a_texto&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Html2TextTransformer&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;documentos_texto_plano&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;transformador_html_a_texto&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;transform_documents&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;documentos_html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;documentos_texto_plano&lt;/span&gt;[&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;]&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;page_content&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;dividir_texto_en_fragmentos&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;texto&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;Document&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; Divide un texto intentando mantener oraciones y párrafos completos.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;separador_recursivo&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;separators&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#98c379"&gt;\n\n&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#98c379"&gt;\n&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34; &amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;chunk_size&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1000&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;chunk_overlap&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;200&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;separador_recursivo&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;create_documents&lt;/span&gt;([&lt;span style="color:#e06c75"&gt;texto&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;crear_modelo_embeddings&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;HuggingFaceEmbeddings&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; Instancia el modelo de embeddings que convertirá cada chunk en un vector.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;HuggingFaceEmbeddings&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;model_name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;sentence-transformers/all-mpnet-base-v2&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;construir_base_vectorial&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;fragmentos&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;Document&lt;/span&gt;], &lt;span style="color:#e06c75"&gt;modelo_embeddings&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;HuggingFaceEmbeddings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;FAISS&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; Genera el embedding de cada chunk y los indexa en una base vectorial FAISS.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;FAISS&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;from_documents&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;fragmentos&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;modelo_embeddings&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;ejecutar_flujo_indexacion&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; Flujo principal: carga, fragmenta, convierte a embeddings e indexa.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#98c379"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Iniciando la descarga y procesamiento del documento...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;contenido_limpio&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;cargar_y_limpiar_documento&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;fragmentos&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;dividir_texto_en_fragmentos&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;contenido_limpio&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;Se crearon &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;len&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;fragmentos&lt;/span&gt;)&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; fragmentos&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;modelo_embeddings&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;crear_modelo_embeddings&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;base_vectorial&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;construir_base_vectorial&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;fragmentos&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;modelo_embeddings&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;base_vectorial&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;save_local&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;RUTA_INDICE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;Se indexaron &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;base_vectorial&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;index&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;ntotal&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; fragmentos en &amp;#39;&lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;RUTA_INDICE&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;if&lt;/span&gt; &lt;span style="color:#e06c75"&gt;__name__&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;==&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;run&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ejecutar_flujo_indexacion&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="verificación-rápida"&gt;Verificación rápida&lt;/h3&gt;
&lt;p&gt;Con la base vectorial ya construida, podemos comprobar que la indexación funcionó haciendo una búsqueda por similitud directamente sobre FAISS, sin pasar todavía por un LLM:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;base_vectorial&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;FAISS&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;load_local&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;RUTA_INDICE&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;crear_modelo_embeddings&lt;/span&gt;(), &lt;span style="color:#e06c75"&gt;allow_dangerous_deserialization&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;resultados&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;base_vectorial&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;similarity_search&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;¿Qué equipos jugarán la semifinal de la Copa del Mundo 2026?&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;resultados&lt;/span&gt;[&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;]&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;page_content&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Si todo salió bien, el chunk más relevante debería contener información sobre las semifinales del torneo — justo lo que el LLM no podía responder en el &lt;a href="https://blog.dacadev.com/generative-ai/rag/que-es-un-rag/"



 


&gt;primer artículo&lt;/a&gt; de la serie.&lt;/p&gt;
&lt;h2 id="conclusión-y-próximos-pasos"&gt;Conclusión y próximos pasos&lt;/h2&gt;
&lt;p&gt;Ya tenemos un &lt;strong&gt;indexing pipeline&lt;/strong&gt; funcional de punta a punta: carga los datos, los fragmenta en chunks manejables, los convierte en embeddings y los almacena en una base vectorial lista para consultarse. Esa base es exactamente lo que el &lt;strong&gt;retriever&lt;/strong&gt; necesita para hacer su trabajo.&lt;/p&gt;
&lt;p&gt;En el siguiente artículo construiremos el &lt;strong&gt;retrieval pipeline&lt;/strong&gt;: cómo el retriever consulta esta base vectorial, arma el contexto y lo combina con el prompt del usuario antes de llegar al LLM.&lt;/p&gt;</content:encoded></item><item><title>Arquitectura de un RAG: Indexing y Retrieval Pipeline</title><link>https://blog.dacadev.com/generative-ai/rag/arquitectura-de-un-rag/</link><pubDate>Tue, 14 Jul 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/generative-ai/rag/arquitectura-de-un-rag/</guid><dc:creator>Dacadev</dc:creator><category>IA generativa</category><description>Descubre la arquitectura de un sistema RAG: el indexing pipeline, el retrieval pipeline y cómo evaluar su calidad con el RAG Triad.</description><media:content url="https://blog.dacadev.com/images/generative-ai/rag/02-arquitectura-de-un-rag/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#los-dos-pipelines-de-un-sistema-rag"&gt;Los dos pipelines de un sistema RAG&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#el-indexing-pipeline"&gt;El indexing pipeline&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#el-retrieval-pipeline"&gt;El retrieval pipeline&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#arquitectura-completa"&gt;Arquitectura completa&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#evaluación"&gt;Evaluación&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión-y-próximos-pasos"&gt;Conclusión y próximos pasos&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;En el &lt;a href="https://blog.dacadev.com/generative-ai/rag/que-es-un-rag/"



 


&gt;artículo anterior de esta serie&lt;/a&gt; se habló de qué es un RAG y cómo ayuda a proveer de conocimiento privado y actualizado a los &lt;strong&gt;LLMs&lt;/strong&gt;. Ahora abordemos el tema de &lt;em&gt;&amp;ldquo;cómo se estructura internamente un &lt;strong&gt;sistema RAG (Retrieval Augmented Generation)&lt;/strong&gt;&amp;rdquo;&lt;/em&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Este es el segundo artículo de la serie &lt;strong&gt;RAGs&lt;/strong&gt;. Al terminar comprenderás la arquitectura de un RAG: el &lt;strong&gt;indexing pipeline&lt;/strong&gt; que prepara el conocimiento, el &lt;strong&gt;retrieval pipeline&lt;/strong&gt; que responde en tiempo real, y el componente de &lt;strong&gt;evaluación&lt;/strong&gt; que garantiza la calidad en producción. 🚀&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="los-dos-pipelines-de-un-sistema-rag"&gt;Los dos pipelines de un sistema RAG&lt;/h2&gt;
&lt;p&gt;Un sistema RAG se puede descomponer en dos pipelines complementarios: el &lt;strong&gt;indexing pipeline&lt;/strong&gt; (pipeline de indexación) y el &lt;strong&gt;retrieval pipeline&lt;/strong&gt; (pipeline de recuperación).&lt;/p&gt;
&lt;p&gt;La distinción es fundamentalmente temporal. El indexing pipeline se ejecuta de forma &lt;strong&gt;offline o asíncrona&lt;/strong&gt;, preparando la base de conocimiento. El retrieval pipeline se ejecuta en &lt;strong&gt;tiempo real&lt;/strong&gt; y es el encargado de responder a cada petición del usuario consumiendo el conocimiento ya indexado.&lt;/p&gt;
&lt;h2 id="el-indexing-pipeline"&gt;El indexing pipeline&lt;/h2&gt;
&lt;p&gt;El &lt;strong&gt;indexing pipeline&lt;/strong&gt; es el responsable de tomar los datos crudos, dividirlos en fragmentos procesables, convertirlos en vectores numéricos —los &lt;strong&gt;embeddings&lt;/strong&gt;— y almacenarlos en una base de datos, típicamente una &lt;strong&gt;base de datos vectorial&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;El flujo parte de la fuente de datos y encadena cuatro etapas de procesamiento hasta almacenar el conocimiento en la base de datos vectorial:&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 F[&amp;#34;📄 Fuente de datos&amp;#34;] --&amp;gt; CA[&amp;#34;📥 Carga&amp;#34;]
 CA --&amp;gt; FR[&amp;#34;✂️ Fragmentación&amp;#34;]
 FR --&amp;gt; CO[&amp;#34;🧮 Conversión&amp;#34;]
 CO --&amp;gt; AL[(&amp;#34;🗄️ Almacenamiento&amp;#34;)]
&lt;/pre&gt;

&lt;p&gt;Cada nodo del diagrama se corresponde con una etapa lógica bien definida:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fuente de datos&lt;/strong&gt;: el origen de la información cruda —bases de datos, APIs, archivos o páginas web— que alimenta el sistema.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Carga&lt;/strong&gt;: se conecta a las fuentes externas, extrae los documentos y parsea su contenido a texto plano.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fragmentación&lt;/strong&gt;: divide los documentos extensos en piezas más pequeñas y manejables, denominadas &lt;strong&gt;chunks&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conversión&lt;/strong&gt;: transforma cada chunk en un vector numérico —el &lt;strong&gt;embedding&lt;/strong&gt;— que captura su significado semántico.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Almacenamiento&lt;/strong&gt;: persiste los embeddings en una &lt;strong&gt;base de datos vectorial&lt;/strong&gt;, lista para la fase de recuperación.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;El indexing pipeline no se ejecuta en cada consulta. Su activación depende de la volatilidad de la fuente de datos y suele responder a &lt;strong&gt;disparadores&lt;/strong&gt; concretos: la carga de un documento nuevo, la actualización de un registro o una reindexación programada. Al ser un proceso offline, podemos permitirnos operaciones costosas sin afectar la latencia de respuesta al usuario.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Tanto la estrategia de &lt;strong&gt;chunking&lt;/strong&gt; como la generación de &lt;strong&gt;embeddings&lt;/strong&gt; son decisiones de diseño con un impacto directo en la calidad del sistema. Las abordaremos en profundidad más adelante en la serie.&lt;/p&gt;
&lt;h2 id="el-retrieval-pipeline"&gt;El retrieval pipeline&lt;/h2&gt;
&lt;p&gt;El &lt;strong&gt;retrieval pipeline&lt;/strong&gt; es el que opera en tiempo real. Su responsabilidad es analizar la petición del usuario, recuperar de la base de datos vectorial los fragmentos de información más relacionados con ella, inyectarlos en el prompt junto con la consulta original, enviar el resultado al LLM y devolver la respuesta.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 U[&amp;#34;👤 Usuario&amp;lt;br/&amp;gt;(prompt)&amp;#34;] --&amp;gt; R[&amp;#34;🔎 Retriever&amp;#34;]
 R --&amp;gt;|&amp;#34;search query&amp;#34;| DB[(&amp;#34;🗄️ Vector DB&amp;lt;br/&amp;gt;memoria no paramétrica&amp;#34;)]
 DB --&amp;gt;|&amp;#34;fetch information&amp;#34;| R
 R --&amp;gt;|&amp;#34;prompt + contexto&amp;#34;| L[&amp;#34;🧠 LLM&amp;lt;br/&amp;gt;memoria paramétrica&amp;#34;]
 L --&amp;gt; RESP[&amp;#34;💬 Respuesta&amp;#34;]
&lt;/pre&gt;

&lt;p&gt;Este flujo introduce una distinción conceptual relevante entre dos tipos de memoria:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Memoria paramétrica&lt;/strong&gt;: el conocimiento codificado en los pesos del LLM durante su entrenamiento.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memoria no paramétrica&lt;/strong&gt;: el conocimiento externo almacenado en la base de datos vectorial, que el sistema consulta dinámicamente.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;El retrieval pipeline es, en esencia, el mecanismo que combina ambas memorias para producir una respuesta fundamentada y este se organiza en tres fases secuenciales, cada una soportada por un componente:&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 A[&amp;#34;🔎 Retrieval&amp;lt;br/&amp;gt;recupera contexto&amp;#34;] --&amp;gt; B[&amp;#34;🧩 Augmentation&amp;lt;br/&amp;gt;construye el prompt&amp;#34;]
 B --&amp;gt; G[&amp;#34;🧠 Generation&amp;lt;br/&amp;gt;genera la respuesta&amp;#34;]
&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Retrieval&lt;/strong&gt;: el &lt;strong&gt;Retriever&lt;/strong&gt; es el componente central del RAG. Busca en la base de conocimiento y recupera los fragmentos relevantes para la consulta.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Augmentation&lt;/strong&gt;: la capa de &lt;strong&gt;gestión de prompts&lt;/strong&gt; combina la información recuperada con la petición original para construir el prompt final.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generation&lt;/strong&gt;: el &lt;strong&gt;componente LLM&lt;/strong&gt; genera la respuesta definitiva. Puede apoyarse en modelos fundacionales o afinados, de código abierto o cerrado.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;La calidad de la respuesta está acotada por la fase de &lt;em&gt;Retrieval&lt;/em&gt;. Si el Retriever recupera fragmentos irrelevantes, ninguna capacidad del LLM compensará ese contexto deficiente. Optimizar la recuperación suele rendir más que cambiar a un modelo más potente.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="arquitectura-completa"&gt;Arquitectura completa&lt;/h2&gt;
&lt;p&gt;Ambos pipelines no operan de forma aislada; convergen en la &lt;strong&gt;base de conocimiento&lt;/strong&gt;. El indexing pipeline la construye y la mantiene actualizada, mientras que el retrieval pipeline la consulta para fundamentar cada respuesta.&lt;/p&gt;




 
 
 
 &lt;div class="flex justify-center"&gt;
 &lt;img
 src="https://blog.dacadev.com/images/generative-ai/rag/02-arquitectura-de-un-rag/rag-architecture_hu_d6115f518ece95d9.webp"
 alt="Imagen guia del contenido de la página"/&gt;
 &lt;/div&gt;
 
 
 


&lt;p&gt;Esta arquitectura desacoplada es lo que confiere al patrón RAG su principal ventaja operativa: actualizar el conocimiento del sistema no requiere reentrenar el modelo, sino únicamente ejecutar el indexing pipeline sobre los nuevos datos.&lt;/p&gt;
&lt;h2 id="evaluación"&gt;Evaluación&lt;/h2&gt;
&lt;p&gt;Hasta aquí hemos descrito los dos componentes estructurales del sistema. Sin embargo, en un entorno de producción es crucial incorporar un tercer componente: la &lt;strong&gt;evaluación&lt;/strong&gt;, encargada de medir si las respuestas que entrega el sistema son correctas y relevantes.&lt;/p&gt;
&lt;p&gt;Un punto de partida sólido es el &lt;strong&gt;RAG Triad&lt;/strong&gt; propuesto por &lt;a href="https://truera.com/ai-quality-education/generative-ai-rags/what-is-the-rag-triad/"




 target="_blank"
 


&gt;TruEra&lt;/a&gt;, un marco que evalúa la coherencia entre las tres piezas de una interacción: la consulta del usuario, el contexto recuperado y la respuesta generada.&lt;/p&gt;




 
 
 
 &lt;div class="flex justify-center"&gt;
 &lt;img
 src="https://blog.dacadev.com/images/generative-ai/rag/02-arquitectura-de-un-rag/rag-triad_hu_81bc0f3ab1929222.webp"
 alt="Imagen guia del contenido de la página"/&gt;
 &lt;/div&gt;
 
 
 


&lt;p&gt;El marco define tres validaciones, una por cada arista del triángulo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Context relevance&lt;/strong&gt;: ¿el contexto recuperado de la base de conocimiento es relevante para la consulta del usuario? Evalúa la calidad de la fase de &lt;em&gt;Retrieval&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Groundedness&lt;/strong&gt;: ¿la respuesta del LLM se apoya fielmente en el contexto recuperado, en lugar de alucinar? Evalúa que el modelo utilice la información proporcionada.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Answer relevance&lt;/strong&gt;: ¿la respuesta final responde efectivamente a la consulta del usuario? Evalúa la utilidad del resultado.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Un sistema RAG sin evaluación es un sistema opaco. Sin medir &lt;em&gt;context relevance&lt;/em&gt;, &lt;em&gt;groundedness&lt;/em&gt; y &lt;em&gt;answer relevance&lt;/em&gt; no podrás distinguir si un fallo proviene de una recuperación deficiente o de una generación defectuosa, lo que vuelve la depuración prácticamente imposible.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="conclusión-y-próximos-pasos"&gt;Conclusión y próximos pasos&lt;/h2&gt;
&lt;p&gt;La arquitectura de un RAG se sostiene sobre dos pipelines desacoplados —indexación offline y recuperación en tiempo real— que convergen en una base de conocimiento vectorial, más un componente transversal de evaluación que garantiza su fiabilidad en producción.&lt;/p&gt;
&lt;p&gt;Con este mapa arquitectónico claro, las próximas entregas de la serie &lt;strong&gt;RAGs&lt;/strong&gt; profundizarán en cada pieza:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Estrategias de &lt;strong&gt;chunking&lt;/strong&gt;: cómo fragmentar los documentos sin perder contexto.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Embeddings&lt;/strong&gt;: qué son, cómo se generan y cómo capturan el significado semántico.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bases de datos vectoriales&lt;/strong&gt;: indexación y búsqueda por similitud.&lt;/li&gt;
&lt;li&gt;Métricas y herramientas para evaluar sistemas RAG de forma rigurosa.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En el siguiente artículo comenzaremos a construir el indexing pipeline, empezando por la fase de carga y fragmentación de datos.&lt;/p&gt;</content:encoded></item><item><title>RAG: Qué es y Cómo Funciona Retrieval Augmented Generation</title><link>https://blog.dacadev.com/generative-ai/rag/que-es-un-rag/</link><pubDate>Mon, 13 Jul 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/generative-ai/rag/que-es-un-rag/</guid><dc:creator>Dacadev</dc:creator><category>IA generativa</category><description>Descubre qué es un RAG, cómo Retrieval Augmented Generation resuelve las alucinaciones de los LLMs y por qué es clave en la IA generativa.</description><media:content url="https://blog.dacadev.com/images/generative-ai/rag/01-que-es-un-rag/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#las-limitaciones-estructurales-de-los-llms"&gt;Las limitaciones estructurales de los LLMs&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#alucinaciones"&gt;Alucinaciones&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conocimiento-con-fecha-de-corte"&gt;Conocimiento con fecha de corte&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#ausencia-de-conocimiento-privado"&gt;Ausencia de conocimiento privado&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#alternativas-antes-de-llegar-a-rag"&gt;Alternativas antes de llegar a RAG&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#agentes"&gt;Agentes&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#fine-tuning"&gt;Fine-tuning&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#qué-es-un-rag-retrieval-augmented-generation"&gt;Qué es un RAG (Retrieval Augmented Generation)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#cómo-funciona-un-rag-a-alto-nivel"&gt;Cómo funciona un RAG a alto nivel&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#ventajas-de-adoptar-un-rag"&gt;Ventajas de adoptar un RAG&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Supongamos que debemos desplegar un asistente conversacional sobre la documentación interna de una organización: manuales técnicos, contratos y políticas que se actualizan cada semana. El modelo base responde con fluidez sobre conocimiento general, pero desconoce por completo esos documentos privados e inventa respuestas con total seguridad cuando se le pregunta por ellos. Aquí es donde &lt;strong&gt;RAG (Retrieval Augmented Generation)&lt;/strong&gt; se convierte en la aproximación arquitectónica más rentable para dotar a un &lt;strong&gt;LLM&lt;/strong&gt; de información precisa, privada y actualizada.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Este es el primer artículo de la serie &lt;strong&gt;RAGs&lt;/strong&gt;. Al terminar podrás explicar qué es un RAG, cómo funciona a alto nivel y por qué se ha vuelto una pieza central en el diseño de aplicaciones de IA generativa. 🚀&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="las-limitaciones-estructurales-de-los-llms"&gt;Las limitaciones estructurales de los LLMs&lt;/h2&gt;
&lt;p&gt;Antes de definir qué es un RAG, es crucial entender las limitaciones de los LLMs que esta técnica resuelve. Un modelo de lenguaje, por potente que sea, arrastra tres restricciones inherentes a la forma en que fue entrenado.&lt;/p&gt;
&lt;h3 id="alucinaciones"&gt;Alucinaciones&lt;/h3&gt;
&lt;p&gt;Las &lt;strong&gt;alucinaciones&lt;/strong&gt; son uno de los problemas más severos de los LLMs. Consisten en que el modelo responde con información incorrecta o inventada, pero con un nivel de confianza que induce al usuario a asumirla como válida.&lt;/p&gt;
&lt;p&gt;En aplicaciones comerciales esto representa un riesgo directo: si la información de entrada es incorrecta, todo el proceso que dependa de ella heredará el error. Consideremos un asistente en el dominio médico; una respuesta errónea sobre la dosificación de un medicamento puede tener consecuencias fatales. La confianza aparente del modelo no es un indicador de veracidad.&lt;/p&gt;
&lt;h3 id="conocimiento-con-fecha-de-corte"&gt;Conocimiento con fecha de corte&lt;/h3&gt;
&lt;p&gt;Los LLMs se entrenan con grandes volúmenes de datos públicos —libros, artículos, páginas web— hasta una &lt;strong&gt;fecha de corte&lt;/strong&gt; determinada. Todo evento posterior a esa fecha queda fuera de su conocimiento.&lt;/p&gt;
&lt;p&gt;Si un modelo fue entrenado con datos hasta 2025, no dispone de información sobre hechos ocurridos después. Ante una consulta de este tipo, el modelo o bien reconoce su desconocimiento, o bien alucina para completar la respuesta.&lt;/p&gt;
&lt;h3 id="ausencia-de-conocimiento-privado"&gt;Ausencia de conocimiento privado&lt;/h3&gt;
&lt;p&gt;Al entrenarse sobre datos públicos, los LLMs no tienen acceso a datos privados: manuales internos, contratos, bases de conocimiento corporativas o historiales de clientes. Esta es una limitación esperada, pero decisiva.&lt;/p&gt;
&lt;p&gt;La alternativa que uno creeria de adjuntar todos los documentos privados en cada conversación no es técnicamente viable, implica un consumo desmedido de tokens y latencia en cada llamada, además de chocar contra los límites de la ventana de contexto.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 L[🧠 LLM entrenado con datos públicos]
 L --&amp;gt; A[❌ Alucinaciones&amp;lt;br/&amp;gt;respuestas inventadas]
 L --&amp;gt; B[❌ Fecha de corte&amp;lt;br/&amp;gt;sin datos recientes]
 L --&amp;gt; C[❌ Sin conocimiento privado&amp;lt;br/&amp;gt;manuales, contratos, datos internos]
&lt;/pre&gt;

&lt;h2 id="alternativas-antes-de-llegar-a-rag"&gt;Alternativas antes de llegar a RAG&lt;/h2&gt;
&lt;p&gt;RAG no es la única técnica para inyectar conocimiento en un LLM. Es importante situarla frente a otras dos aproximaciones habituales y comprender sus contrapartidas.&lt;/p&gt;
&lt;h3 id="agentes"&gt;Agentes&lt;/h3&gt;
&lt;p&gt;Los &lt;strong&gt;agentes&lt;/strong&gt; han ganado tracción gracias a las amplias ventanas de contexto actuales, que permiten al modelo procesar grandes cantidades de información para resolver tareas complejas de manera autonoma. Sin embargo, cuando el volumen documental es elevado, el agente debería leer toda la información en cada ejecución.&lt;/p&gt;
&lt;p&gt;Incluso apoyándose en mecanismos de caché, el costo en tokens y tiempo escala de forma prohibitiva. Procesar íntegramente un manual extenso solo para resolver una consulta puntual es análogo a recorrer una biblioteca completa para responder una única pregunta: funciona, pero es ineficiente.&lt;/p&gt;
&lt;h3 id="fine-tuning"&gt;Fine-tuning&lt;/h3&gt;
&lt;p&gt;El &lt;strong&gt;fine-tuning&lt;/strong&gt; consiste en reentrenar un LLM sobre datos específicos para ajustar sus pesos y especializarlo en un dominio. Esta técnica genera una nueva versión del modelo con el conocimiento incorporado directamente en sus parámetros.&lt;/p&gt;
&lt;p&gt;El problema es su costo operativo: requiere tiempo, recursos y datos de entrenamiento cuidados. Además, cada vez que la información cambia, es necesario reentrenar. En un escenario donde los datos se actualizan cada semana, o cada día, el fine-tuning se vuelve inviable como estrategia principal.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Estas alternativas no son deficientes; simplemente resuelven problemas distintos. Los &lt;strong&gt;agentes&lt;/strong&gt; son idóneos para explorar código o ejecutar flujos de trabajo dinámicos, y el &lt;strong&gt;fine-tuning&lt;/strong&gt; brilla cuando el conocimiento es estable y muy específico. RAG destaca precisamente donde estas fallan: conocimiento amplio, cambiante y verificable.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="qué-es-un-rag-retrieval-augmented-generation"&gt;Qué es un RAG (Retrieval Augmented Generation)&lt;/h2&gt;
&lt;p&gt;Un &lt;strong&gt;RAG (Retrieval Augmented Generation)&lt;/strong&gt; es una técnica que recupera información relevante desde una fuente de datos externa y la incorpora al contexto del LLM en tiempo de inferencia, de modo que el modelo pueda responder con información verídica y actualizada.&lt;/p&gt;
&lt;p&gt;La idea central es desacoplar el conocimiento del modelo. En lugar de codificar los datos en los pesos, como hace el fine-tuning, o de arrastrar todo el corpus en cada llamada, como hace un agente, el RAG selecciona únicamente los fragmentos pertinentes para cada consulta y los añade al prompt.&lt;/p&gt;
&lt;p&gt;Analicemos un caso concreto. Supongamos un modelo cuyo conocimiento llega hasta mayo de 2026 y le preguntamos por un evento posterior a esa fecha:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;prompt: ¿Qué equipos jugarán la semifinal de la Copa del Mundo 2026?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;LLM: Lo siento, no dispongo de información sobre los equipos que jugarán
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; la semifinal de la Copa del Mundo 2026. Mi conocimiento está
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; actualizado hasta mayo de 2026.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ahora enriquezcamos ese mismo prompt con un bloque de contexto recuperado desde una fuente externa:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;prompt: ¿Qué equipos jugarán la semifinal de la Copa del Mundo 2026?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----- contexto inyectado -----
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Contexto: Los equipos que disputarán la semifinal de la Copa del Mundo 2026 son:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- Francia
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- España
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- Inglaterra
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- Argentina
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;----- fin del contexto -----
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;LLM: Los equipos que jugarán la semifinal de la Copa del Mundo 2026 son
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Francia, España, Inglaterra y Argentina.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La diferencia está en el campo de &lt;strong&gt;contexto&lt;/strong&gt;. Ese bloque, recuperado dinámicamente, es lo que permite al modelo responder con precisión sin haber sido entrenado con esa información. En esto consiste, en esencia, un RAG: obtener el conocimiento relevante desde una fuente de datos y aumentar con él el contexto del LLM.&lt;/p&gt;
&lt;p&gt;Si pensamos esto en el caso de la documentación extensa, un RAG permite extraer las secciones pertinentes de un manual o contrato y añadirlas al prompt, de modo que el modelo pueda responder con información verídica y actualizada sin necesidad de reentrenar ni de procesar todo el documento en cada consulta. Es decir que solo cargamos una parte del documento y no todo su contenido.&lt;/p&gt;
&lt;h2 id="cómo-funciona-un-rag-a-alto-nivel"&gt;Cómo funciona un RAG a alto nivel&lt;/h2&gt;
&lt;p&gt;Su nombre describe con exactitud las tres fases del proceso: &lt;strong&gt;Retrieval&lt;/strong&gt; (recuperación), &lt;strong&gt;Augmented&lt;/strong&gt; (aumento) y &lt;strong&gt;Generation&lt;/strong&gt; (generación).&lt;/p&gt;




 
 
 
 &lt;div class="flex justify-center"&gt;
 &lt;img
 src="https://blog.dacadev.com/images/generative-ai/rag/01-que-es-un-rag/rag-diagram_hu_ae75a4373e1dc204.webp"
 alt="Imagen guia del contenido de la página"/&gt;
 &lt;/div&gt;
 
 
 


&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Retrieval (Recuperación)&lt;/strong&gt;: ante una consulta del usuario, el sistema busca en una base de conocimiento externa los fragmentos de información más relevantes. Esta búsqueda suele apoyarse en similitud semántica, un mecanismo que abordaremos en detalle más adelante en la serie.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Augmented (Aumento)&lt;/strong&gt;: los fragmentos recuperados se combinan con la consulta original para construir un prompt enriquecido. El modelo recibe así, junto a la pregunta, el contexto necesario para responderla.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generation (Generación)&lt;/strong&gt;: el LLM genera la respuesta final apoyándose en el contexto inyectado, no solo en su conocimiento paramétrico.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;La calidad de un RAG depende directamente de la fase de recuperación. Si los fragmentos recuperados son irrelevantes o incompletos, el modelo generará una respuesta pobre por muy capaz que sea. En RAG, la máxima &amp;ldquo;basura entra, basura sale&amp;rdquo; aplica con especial fuerza.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="ventajas-de-adoptar-un-rag"&gt;Ventajas de adoptar un RAG&lt;/h2&gt;
&lt;p&gt;Más allá de mitigar las limitaciones descritas, el patrón RAG ofrece beneficios concretos de ingeniería:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Eficiencia y costo&lt;/strong&gt;: aporta conocimiento profundo y específico al modelo sin el costo de reentrenar ni de procesar el documento completo en cada llamada.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Información verificable&lt;/strong&gt;: al recuperar fragmentos de fuentes reales, el modelo puede &lt;strong&gt;citar&lt;/strong&gt; su origen, de modo que el usuario contraste la respuesta con la fuente original.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Actualización simple&lt;/strong&gt;: mantener el sistema al día se reduce a actualizar la base de conocimiento, sin tocar el modelo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reducción de alucinaciones&lt;/strong&gt;: al fundamentar la respuesta en datos recuperados, disminuye de forma significativa la probabilidad de que el modelo invente información.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Un RAG reduce las alucinaciones, pero no las elimina por completo. El modelo aún puede malinterpretar el contexto recuperado o combinarlo con su conocimiento paramétrico de forma incorrecta. El diseño del prompt y la evaluación rigurosa siguen siendo responsabilidad del ingeniero.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>Patrones de Diseño: Factory</title><link>https://blog.dacadev.com/programacion/patrones-de-diseno/fabrica/</link><pubDate>Tue, 07 Jul 2026 00:00:00 +0000</pubDate><guid>https://blog.dacadev.com/programacion/patrones-de-diseno/fabrica/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Aprende los patrones de fabricación (Simple, Factory Method y Abstract Factory) en Python y cómo se relacionan con el principio de inversión de dependencias.</description><media:content url="https://blog.dacadev.com/images/programming/design-patterns/factory/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#simple-factory"&gt;Simple Factory&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#factory-method"&gt;Factory Method&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#abstract-factory"&gt;Abstract Factory&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#factory-method-vs-abstract-factory"&gt;Factory Method vs Abstract Factory&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#static-factory"&gt;Static Factory&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#principio-de-inversión-de-dependencias"&gt;Principio de Inversión de Dependencias&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#consideraciones"&gt;Consideraciones&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#continúa-la-serie"&gt;Continúa la serie&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;La instanciación directa de clases concretas es uno de los puntos más costosos de acoplamiento en un diseño orientado a objetos. Cada &lt;code&gt;new&lt;/code&gt; o llamada explícita a un constructor ata al cliente a una implementación específica, dificultando la extensión y la sustitución de componentes. Los &lt;strong&gt;patrones factory&lt;/strong&gt; encapsulan esa decisión en un lugar controlado, permitiendo evolucionar la creación de objetos sin propagar cambios a todo el código consumidor.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 Los patrones &lt;strong&gt;factory&lt;/strong&gt; encapsulan la creación de objetos y desacoplan al cliente de las clases concretas que necesita instanciar.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Este artículo forma parte de la serie de &lt;a href="https://blog.dacadev.com/programacion/patrones-de-diseno/que-son"



 


&gt;patrones de diseño&lt;/a&gt;. Analizaremos tres variantes de fabricación (&lt;strong&gt;Simple Factory&lt;/strong&gt;, &lt;strong&gt;Factory Method&lt;/strong&gt; y &lt;strong&gt;Abstract Factory&lt;/strong&gt;), su relación con el &lt;strong&gt;Principio de Inversión de Dependencias&lt;/strong&gt; y los trade-offs que conviene considerar al elegir uno u otro.&lt;/p&gt;
&lt;h2 id="simple-factory"&gt;Simple Factory&lt;/h2&gt;
&lt;p&gt;El &lt;strong&gt;Simple Factory&lt;/strong&gt; no es un patrón de diseño formal del catálogo GoF, sino un idiom recurrente: encapsular la lógica de creación de objetos dentro de un método (usualmente estático) que decide qué instancia devolver en función de un parámetro. Es un buen punto de partida para entender los patrones que veremos a continuación.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;strong&gt;GoF&lt;/strong&gt; significa &lt;strong&gt;&amp;ldquo;Gang of Four&amp;rdquo;&lt;/strong&gt; (la &amp;ldquo;Banda de los Cuatro&amp;rdquo;): los cuatro autores del libro &lt;em&gt;Design Patterns&lt;/em&gt; (1994) que catalogó los 23 patrones de diseño clásicos. Cuando decimos que un patrón &amp;ldquo;es GoF&amp;rdquo;, significa que aparece en ese catálogo original.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Supongamos una pizzería que produce distintos tipos de pizzas. Sin un factory, el cliente tendría que conocer todas las clases concretas y decidir cuál instanciar. Con un &lt;code&gt;SimpleFactory&lt;/code&gt; esa decisión queda centralizada:&lt;/p&gt;
&lt;pre class="mermaid"&gt;classDiagram
 class PizzaStore {
 -factory: SimplePizzaFactory
 +order_pizza(kind) Pizza
 }
 class SimplePizzaFactory {
 +create_pizza(kind) Pizza
 }
 class Pizza {
 &amp;lt;&amp;lt;abstract&amp;gt;&amp;gt;
 +prepare()
 +bake()
 +box()
 }
 class CheesePizza
 class VeggiePizza
 class PepperoniPizza

 PizzaStore --&amp;gt; SimplePizzaFactory : usa
 SimplePizzaFactory ..&amp;gt; Pizza : crea
 Pizza &amp;lt;|-- CheesePizza
 Pizza &amp;lt;|-- VeggiePizza
 Pizza &amp;lt;|-- PepperoniPizza
&lt;/pre&gt;

&lt;p&gt;Implementación mínima en Python:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;abc&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Pizza&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;prepare&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;: &lt;span style="color:#56b6c2"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;bake&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Horneando la pizza&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;box&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Empacando la pizza&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;CheesePizza&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Pizza&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;prepare&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Preparando pizza de queso&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;VeggiePizza&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Pizza&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;prepare&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Preparando pizza vegetariana&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;SimplePizzaFactory&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;create_pizza&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;kind&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pizza&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; &lt;span style="color:#e06c75"&gt;kind&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;==&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;cheese&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;CheesePizza&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; &lt;span style="color:#e06c75"&gt;kind&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;==&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;veggie&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;VeggiePizza&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;raise&lt;/span&gt; &lt;span style="color:#e06c75"&gt;ValueError&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;Tipo de pizza no soportado: &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;kind&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;PizzaStore&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;factory&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;SimplePizzaFactory&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;factory&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;factory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;order_pizza&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;kind&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pizza&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;pizza&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;factory&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;create_pizza&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;kind&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;pizza&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;prepare&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;pizza&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;bake&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;pizza&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;box&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;pizza&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El cliente (&lt;code&gt;PizzaStore&lt;/code&gt;) ya no depende de las clases concretas; toda la lógica de selección vive en el factory. La limitación es evidente: si necesitamos que distintas sucursales produzcan variantes propias de cada pizza, el &lt;code&gt;if/elif&lt;/code&gt; termina explotando. Ese es exactamente el problema que resuelve &lt;strong&gt;Factory Method&lt;/strong&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;El Simple Factory es útil como técnica de refactor cuando queremos aislar una serie de condicionales de creación, pero &lt;strong&gt;no&lt;/strong&gt; ofrece extensibilidad vía herencia.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="factory-method"&gt;Factory Method&lt;/h2&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;El &lt;strong&gt;Factory Method&lt;/strong&gt; define una interfaz para crear un objeto, pero delega en las subclases la decisión de qué clase concreta instanciar.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;En lugar de tener una única clase factory que decide con condicionales, el &lt;strong&gt;Factory Method&lt;/strong&gt; define un método abstracto de creación en la superclase. Cada subclase implementa ese método y devuelve el producto concreto que corresponda. La instanciación se &lt;strong&gt;difiere&lt;/strong&gt; a las subclases.&lt;/p&gt;
&lt;pre class="mermaid"&gt;classDiagram
 class Creator {
 &amp;lt;&amp;lt;abstract&amp;gt;&amp;gt;
 +factory_method() Product
 +operation()
 }
 class ConcreteCreatorA {
 +factory_method() Product
 }
 class ConcreteCreatorB {
 +factory_method() Product
 }
 class Product {
 &amp;lt;&amp;lt;abstract&amp;gt;&amp;gt;
 }
 class ConcreteProductA
 class ConcreteProductB

 Creator &amp;lt;|-- ConcreteCreatorA
 Creator &amp;lt;|-- ConcreteCreatorB
 Product &amp;lt;|-- ConcreteProductA
 Product &amp;lt;|-- ConcreteProductB
 ConcreteCreatorA ..&amp;gt; ConcreteProductA : crea
 ConcreteCreatorB ..&amp;gt; ConcreteProductB : crea
&lt;/pre&gt;

&lt;p&gt;Consideremos un ejemplo canónico: una jerarquía de animales donde cada subclase decide qué instancia producir. La superclase define el flujo (&lt;code&gt;show_animal&lt;/code&gt;) que consume el producto creado por el &lt;code&gt;factory_method&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;abc&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Animal&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;make_sound&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;: &lt;span style="color:#56b6c2"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;create_animal&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;Animal&amp;#34;&lt;/span&gt;: &lt;span style="color:#56b6c2"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;show_animal&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;animal&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;create_animal&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;El animal dice: &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;animal&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;make_sound&lt;/span&gt;()&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Dog&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Animal&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;make_sound&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;Guau!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;create_animal&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Animal&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Dog&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Cat&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Animal&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;make_sound&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;Miau!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;create_animal&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Animal&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Cat&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;Dog&lt;/span&gt;()&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;show_animal&lt;/span&gt;() &lt;span style="color:#7f848e"&gt;# El animal dice: Guau!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;Cat&lt;/span&gt;()&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;show_animal&lt;/span&gt;() &lt;span style="color:#7f848e"&gt;# El animal dice: Miau!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El punto clave es que &lt;code&gt;Animal.show_animal&lt;/code&gt; es &lt;strong&gt;agnóstico&lt;/strong&gt; a la clase concreta: opera sobre la abstracción &lt;code&gt;Animal&lt;/code&gt; y delega la instanciación a &lt;code&gt;create_animal&lt;/code&gt;. Añadir un nuevo animal implica una nueva subclase, no modificar código existente — cumpliendo el principio abierto/cerrado.&lt;/p&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Factory Method depende de &lt;strong&gt;herencia&lt;/strong&gt;: cada subclase implementa el método de creación. Es ideal cuando la variación entre productos está atada a la variación de la clase creadora.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="abstract-factory"&gt;Abstract Factory&lt;/h2&gt;
&lt;p&gt;Mientras Factory Method crea &lt;strong&gt;un&lt;/strong&gt; producto, el &lt;strong&gt;Abstract Factory&lt;/strong&gt; crea &lt;strong&gt;familias completas&lt;/strong&gt; de productos relacionados sin acoplar al cliente a las clases concretas de cada familia.&lt;/p&gt;
&lt;p&gt;Un caso clásico: una aplicación que renderiza componentes de UI para distintos sistemas operativos. Botones y checkboxes de Windows deben usarse juntos, igual que los de macOS; mezclarlos rompe la coherencia visual. El Abstract Factory garantiza que solo se combinen componentes de la misma familia.&lt;/p&gt;
&lt;pre class="mermaid"&gt;classDiagram
 class GUIFactory {
 &amp;lt;&amp;lt;abstract&amp;gt;&amp;gt;
 +create_button() Button
 +create_checkbox() Checkbox
 }
 class WindowsFactory
 class MacFactory
 class Button {
 &amp;lt;&amp;lt;abstract&amp;gt;&amp;gt;
 +render()
 }
 class Checkbox {
 &amp;lt;&amp;lt;abstract&amp;gt;&amp;gt;
 +render()
 }
 class WindowsButton
 class WindowsCheckbox
 class MacButton
 class MacCheckbox

 GUIFactory &amp;lt;|-- WindowsFactory
 GUIFactory &amp;lt;|-- MacFactory
 Button &amp;lt;|-- WindowsButton
 Button &amp;lt;|-- MacButton
 Checkbox &amp;lt;|-- WindowsCheckbox
 Checkbox &amp;lt;|-- MacCheckbox
 WindowsFactory ..&amp;gt; WindowsButton : crea
 WindowsFactory ..&amp;gt; WindowsCheckbox : crea
 MacFactory ..&amp;gt; MacButton : crea
 MacFactory ..&amp;gt; MacCheckbox : crea
&lt;/pre&gt;

&lt;p&gt;Implementación en Python:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;abc&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Button&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;render&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;: &lt;span style="color:#56b6c2"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Checkbox&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;render&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;: &lt;span style="color:#56b6c2"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;WindowsButton&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Button&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;render&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Renderizando botón de Windows&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;WindowsCheckbox&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Checkbox&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;render&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Renderizando checkbox de Windows&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;MacButton&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Button&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;render&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Renderizando botón de macOS&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;MacCheckbox&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Checkbox&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;render&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Renderizando checkbox de macOS&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;GUIFactory&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;create_button&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Button&lt;/span&gt;: &lt;span style="color:#56b6c2"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;create_checkbox&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Checkbox&lt;/span&gt;: &lt;span style="color:#56b6c2"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;WindowsFactory&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;GUIFactory&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;create_button&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Button&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;WindowsButton&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;create_checkbox&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Checkbox&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;WindowsCheckbox&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;MacFactory&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;GUIFactory&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;create_button&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Button&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;MacButton&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;create_checkbox&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Checkbox&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;MacCheckbox&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Application&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;factory&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;GUIFactory&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;factory&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;factory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;create_ui&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;button&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;factory&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;create_button&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;checkbox&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;factory&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;create_checkbox&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;button&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;render&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;checkbox&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;render&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;factory&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;GUIFactory&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;WindowsFactory&lt;/span&gt;() &lt;span style="color:#7f848e"&gt;# o MacFactory()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;Application&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;factory&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;create_ui&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Application&lt;/code&gt; depende exclusivamente de &lt;code&gt;GUIFactory&lt;/code&gt;, &lt;code&gt;Button&lt;/code&gt; y &lt;code&gt;Checkbox&lt;/code&gt; — todas abstracciones. Cambiar de familia consiste en inyectar una factory distinta; el resto del código permanece intacto.&lt;/p&gt;
&lt;h3 id="factory-method-vs-abstract-factory"&gt;Factory Method vs Abstract Factory&lt;/h3&gt;
&lt;p&gt;Aunque comparten espíritu, no son intercambiables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Factory Method&lt;/strong&gt; usa &lt;strong&gt;herencia&lt;/strong&gt;: la subclase decide qué producto crear implementando un método.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Abstract Factory&lt;/strong&gt; usa &lt;strong&gt;composición&lt;/strong&gt;: el cliente recibe una factory y llama a varios métodos de creación sobre ella, obteniendo una familia de productos coherentes.&lt;/li&gt;
&lt;li&gt;Factory Method escala en la dimensión de &amp;ldquo;un producto que varía&amp;rdquo;; Abstract Factory escala en la dimensión de &amp;ldquo;múltiples productos que varían de forma correlacionada&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="static-factory"&gt;Static Factory&lt;/h2&gt;
&lt;p&gt;El &lt;strong&gt;Static Factory&lt;/strong&gt; es una variante ligera que expone métodos de clase estáticos para construir instancias, en lugar de exponer constructores públicos. Es común en librerías del ecosistema Java y en APIs de Python que ofrecen métodos como &lt;code&gt;datetime.now()&lt;/code&gt; o &lt;code&gt;Path.home()&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Connection&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;dsn&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;_dsn&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;dsn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@classmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;from_env&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;cls&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;Connection&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;cls&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;dsn&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e06c75"&gt;os&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;environ&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;DATABASE_URL&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@classmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;in_memory&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;cls&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;Connection&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;cls&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;dsn&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;sqlite://:memory:&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ventajas: los métodos estáticos pueden tener nombres semánticos (&lt;code&gt;from_env&lt;/code&gt;, &lt;code&gt;in_memory&lt;/code&gt;) que documentan la intención mucho mejor que un constructor sobrecargado. Limitación: no permite polimorfismo — no es reemplazable en tiempo de ejecución como sí lo son Factory Method o Abstract Factory.&lt;/p&gt;
&lt;h2 id="principio-de-inversión-de-dependencias"&gt;Principio de Inversión de Dependencias&lt;/h2&gt;
&lt;p&gt;El &lt;strong&gt;Principio de Inversión de Dependencias&lt;/strong&gt; (DIP, la &amp;ldquo;D&amp;rdquo; de SOLID) enuncia dos reglas:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Los módulos de alto nivel no deben depender de módulos de bajo nivel. Ambos deben depender de abstracciones.&lt;/li&gt;
&lt;li&gt;Las abstracciones no deben depender de detalles. Los detalles deben depender de abstracciones.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Los patrones factory son una herramienta natural para aplicar DIP: al centralizar la creación en una abstracción, el módulo de alto nivel deja de instanciar clases concretas. Volviendo al ejemplo de la pizzería:&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 subgraph Antes[&amp;#34;Sin DIP&amp;#34;]
 A1[PizzaStore] --&amp;gt; A2[CheesePizza]
 A1 --&amp;gt; A3[VeggiePizza]
 A1 --&amp;gt; A4[PepperoniPizza]
 end
 subgraph Despues[&amp;#34;Con DIP + Factory&amp;#34;]
 B1[PizzaStore] --&amp;gt; B2[Pizza abstracta]
 B3[CheesePizza] --&amp;gt; B2
 B4[VeggiePizza] --&amp;gt; B2
 B5[PepperoniPizza] --&amp;gt; B2
 end
&lt;/pre&gt;

&lt;p&gt;En &amp;ldquo;Antes&amp;rdquo;, el flujo de dependencia va de alto a bajo nivel: &lt;code&gt;PizzaStore&lt;/code&gt; conoce todas las pizzas concretas. En &amp;ldquo;Después&amp;rdquo;, &lt;strong&gt;ambos&lt;/strong&gt; dependen de la abstracción &lt;code&gt;Pizza&lt;/code&gt;: la dependencia queda &lt;strong&gt;invertida&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Un ejemplo aislado en Python que muestra el patrón:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;abc&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;MessageSender&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;send&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;message&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;: &lt;span style="color:#56b6c2"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;EmailSender&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;MessageSender&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;send&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;message&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;Enviando email: &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;message&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;SmsSender&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;MessageSender&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;send&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;message&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;Enviando SMS: &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;message&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;NotificationService&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;sender&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;MessageSender&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;_sender&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;sender&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;notify&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;message&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;_sender&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;send&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;message&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;NotificationService&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;EmailSender&lt;/span&gt;())&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;notify&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Nuevo despliegue exitoso&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;NotificationService&lt;/code&gt; no conoce &lt;code&gt;EmailSender&lt;/code&gt; ni &lt;code&gt;SmsSender&lt;/code&gt;; solo la abstracción &lt;code&gt;MessageSender&lt;/code&gt;. Un factory puede alimentar esa dependencia según configuración, entorno o feature flags, sin tocar &lt;code&gt;NotificationService&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="consideraciones"&gt;Consideraciones&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Todos los factories encapsulan la creación de objetos y reducen el acoplamiento a implementaciones concretas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simple Factory&lt;/strong&gt; no es un patrón GoF; es un idiom útil para aislar condicionales de creación en un único lugar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Factory Method&lt;/strong&gt; depende de &lt;strong&gt;herencia&lt;/strong&gt;: cada subclase implementa el método de creación y decide el producto concreto.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Abstract Factory&lt;/strong&gt; depende de &lt;strong&gt;composición&lt;/strong&gt;: el cliente recibe una factory y obtiene familias de productos coherentes.&lt;/li&gt;
&lt;li&gt;Los tres refuerzan el &lt;strong&gt;Principio de Inversión de Dependencias&lt;/strong&gt; al hacer que el código cliente dependa de abstracciones, no de tipos concretos.&lt;/li&gt;
&lt;li&gt;El DIP es una guía transversal, no un patrón: aplica siempre que quieras evitar el acoplamiento con implementaciones específicas.&lt;/li&gt;
&lt;li&gt;Factory es una &lt;strong&gt;técnica de diseño&lt;/strong&gt;, no una clase específica. Su nombre puede variar (&lt;code&gt;build&lt;/code&gt;, &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;from_x&lt;/code&gt;), lo importante es la intención: encapsular la construcción de objetos.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 Elige &lt;strong&gt;Simple Factory&lt;/strong&gt; para aislar condicionales, &lt;strong&gt;Factory Method&lt;/strong&gt; cuando la variación está atada a la jerarquía del creador, y &lt;strong&gt;Abstract Factory&lt;/strong&gt; cuando necesitas coherencia entre múltiples productos relacionados.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="continúa-la-serie"&gt;Continúa la serie&lt;/h2&gt;
&lt;p&gt;Si te interesa seguir explorando patrones de diseño, revisa los otros artículos de la serie:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.dacadev.com/programacion/patrones-de-diseno/que-son"



 


&gt;Qué son los patrones de diseño&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.dacadev.com/programacion/patrones-de-diseno/estrategia"



 


&gt;Patrón Estrategia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.dacadev.com/programacion/patrones-de-diseno/observador"



 


&gt;Patrón Observador&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.dacadev.com/programacion/patrones-de-diseno/decorador"



 


&gt;Patrón Decorador&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>TypeScript: Tipos avanzados, subtipos y varianza</title><link>https://blog.dacadev.com/typescript/tipos-avanzados/</link><pubDate>Sun, 21 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/typescript/tipos-avanzados/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Comprende la jerarquía de tipos de TypeScript: subtipos y supertipos, los tipos top y bottom (unknown y never), null, undefined, void y la varianza.</description><media:content url="https://blog.dacadev.com/images/typescript/advanced-types/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#subtipos"&gt;Subtipos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#supertipos"&gt;Supertipos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#la-jerarquía-de-tipos"&gt;La jerarquía de tipos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#los-tipos-especiales-null-undefined-void-y-never"&gt;Los tipos especiales: null, undefined, void y never&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#varianza"&gt;Varianza&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Octavo artículo de la serie sobre &lt;strong&gt;TypeScript&lt;/strong&gt;. Abordaremos la teoría que sustenta el sistema de tipos: subtipos, supertipos, la jerarquía completa, los tipos &lt;code&gt;unknown&lt;/code&gt; y &lt;code&gt;never&lt;/code&gt;, y la varianza.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Comprender la &lt;strong&gt;relación entre tipos&lt;/strong&gt; es lo que separa a quien usa TypeScript de quien lo domina. El compilador decide qué asignaciones son válidas aplicando reglas de subtipado y varianza. Una vez interiorizadas estas reglas, los errores del typechecker dejan de ser obstáculos crípticos y se convierten en información precisa sobre el diseño de tus tipos.&lt;/p&gt;
&lt;h2 id="subtipos"&gt;Subtipos&lt;/h2&gt;
&lt;p&gt;La regla fundamental del subtipado se enuncia así:&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Si tienes un tipo &lt;code&gt;A&lt;/code&gt; y un tipo &lt;code&gt;B&lt;/code&gt; donde &lt;code&gt;B&lt;/code&gt; es &lt;strong&gt;subtipo&lt;/strong&gt; de &lt;code&gt;A&lt;/code&gt;, entonces puedes usar &lt;code&gt;B&lt;/code&gt; en cualquier lugar donde se espere un &lt;code&gt;A&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Algunas relaciones de subtipo en TypeScript:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Array&lt;/code&gt; es subtipo de &lt;code&gt;Object&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Tuple&lt;/code&gt; es subtipo de &lt;code&gt;Array&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Todo es subtipo de &lt;code&gt;any&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;never&lt;/code&gt; es subtipo de todo.&lt;/li&gt;
&lt;li&gt;Si una clase &lt;code&gt;Bird&lt;/code&gt; extiende &lt;code&gt;Animal&lt;/code&gt;, entonces &lt;code&gt;Bird&lt;/code&gt; es subtipo de &lt;code&gt;Animal&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Aplicado a la práctica, esto significa que donde se necesite un &lt;code&gt;Object&lt;/code&gt; puedes usar un &lt;code&gt;Array&lt;/code&gt;; donde se necesite un &lt;code&gt;Array&lt;/code&gt; puedes usar una &lt;code&gt;Tuple&lt;/code&gt;; y donde se necesite un &lt;code&gt;Animal&lt;/code&gt; puedes usar un &lt;code&gt;Bird&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="supertipos"&gt;Supertipos&lt;/h2&gt;
&lt;p&gt;Un supertipo es la relación inversa:&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Si tienes un tipo &lt;code&gt;A&lt;/code&gt; y un tipo &lt;code&gt;B&lt;/code&gt; donde &lt;code&gt;B&lt;/code&gt; es &lt;strong&gt;supertipo&lt;/strong&gt; de &lt;code&gt;A&lt;/code&gt;, entonces puedes usar &lt;code&gt;A&lt;/code&gt; en cualquier lugar donde se espere un &lt;code&gt;B&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Las relaciones de supertipo reflejan en espejo a las anteriores:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Array&lt;/code&gt; es supertipo de &lt;code&gt;Tuple&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Object&lt;/code&gt; es supertipo de &lt;code&gt;Array&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;any&lt;/code&gt; es supertipo de todo.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Animal&lt;/code&gt; es supertipo de &lt;code&gt;Bird&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="la-jerarquía-de-tipos"&gt;La jerarquía de tipos&lt;/h2&gt;
&lt;p&gt;Todas estas relaciones forman una jerarquía con un tipo en la cúspide (&lt;em&gt;top type&lt;/em&gt;) y otro en el fondo (&lt;em&gt;bottom type&lt;/em&gt;):&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 Unknown[unknown - top type] --&amp;gt; Any[any]
 Any --&amp;gt; Number
 Any --&amp;gt; BigInt
 Any --&amp;gt; Boolean
 Any --&amp;gt; String
 Any --&amp;gt; Symbol
 Any --&amp;gt; Object
 Any --&amp;gt; Void
 Any --&amp;gt; Null
 Any --&amp;gt; Undefined
 Object --&amp;gt; Array
 Array --&amp;gt; Tuple
 Object --&amp;gt; Function
 Number --&amp;gt; Never[never - bottom type]
 String --&amp;gt; Never
 Boolean --&amp;gt; Never
 Object --&amp;gt; Never
 Tuple --&amp;gt; Never
&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;unknown&lt;/code&gt;&lt;/strong&gt; es el &lt;em&gt;top type&lt;/em&gt;: todo es asignable a él, pero no permite operar sin acotar primero.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;never&lt;/code&gt;&lt;/strong&gt; es el &lt;em&gt;bottom type&lt;/em&gt;: es subtipo de cualquier otro tipo y representa lo que nunca ocurre.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="los-tipos-especiales-null-undefined-void-y-never"&gt;Los tipos especiales: null, undefined, void y never&lt;/h2&gt;
&lt;p&gt;Estos cuatro tipos modelan la ausencia de valor con matices distintos:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Tipo&lt;/th&gt;
 &lt;th&gt;Significado&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Ausencia explícita de valor&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Variable que aún no recibió un valor&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;void&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Función que no tiene sentencia &lt;code&gt;return&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;never&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Función que nunca retorna&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;La distinción entre &lt;code&gt;void&lt;/code&gt; y &lt;code&gt;never&lt;/code&gt; es sutil pero importante. Una función &lt;code&gt;void&lt;/code&gt; termina sin devolver nada útil; una función &lt;code&gt;never&lt;/code&gt; no termina en absoluto, ya sea porque lanza una excepción o porque entra en un bucle infinito:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// void: termina, no retorna valor
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;msg&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;msg&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// never: nunca completa su ejecución
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;fail&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;message&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;)&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;never&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;throw&lt;/span&gt; &lt;span style="color:#c678dd"&gt;new&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Error&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;message&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;loopForever&lt;/span&gt;()&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;never&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;while&lt;/span&gt; (&lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;code&gt;never&lt;/code&gt; es especialmente útil en la verificación de exhaustividad: si un &lt;code&gt;switch&lt;/code&gt; cubre todos los casos de una unión, la rama &lt;code&gt;default&lt;/code&gt; puede asignar el valor a un &lt;code&gt;never&lt;/code&gt;, y el compilador detectará en tiempo de compilación cualquier caso olvidado al ampliar la unión.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="varianza"&gt;Varianza&lt;/h2&gt;
&lt;p&gt;Determinar si un tipo es sub o supertipo de otro no siempre es evidente, sobre todo al combinar estructuras y funciones. TypeScript dispone de una notación formal para razonar sobre estas relaciones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;A &amp;lt;: B&lt;/code&gt; significa &amp;ldquo;&lt;code&gt;A&lt;/code&gt; es subtipo de, o el mismo tipo que, &lt;code&gt;B&lt;/code&gt;&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;A &amp;gt;: B&lt;/code&gt; significa &amp;ldquo;&lt;code&gt;A&lt;/code&gt; es supertipo de, o el mismo tipo que, &lt;code&gt;B&lt;/code&gt;&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La &lt;strong&gt;varianza&lt;/strong&gt; describe cómo se propagan estas relaciones cuando los tipos se anidan en estructuras (arreglos, objetos) o en firmas de función. Es el motivo por el que, por ejemplo, un arreglo de un subtipo no siempre es intercambiable con un arreglo de su supertipo: la mutabilidad introduce restricciones que el compilador debe respetar para mantener la solidez del sistema.&lt;/p&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;El sistema de tipos de TypeScript es una jerarquía gobernada por reglas de subtipado y varianza, con &lt;code&gt;unknown&lt;/code&gt; como tipo superior y &lt;code&gt;never&lt;/code&gt; como tipo inferior. Distinguir &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;void&lt;/code&gt; y &lt;code&gt;never&lt;/code&gt;, y comprender cómo &lt;code&gt;B &amp;lt;: A&lt;/code&gt; permite sustituir un tipo por otro, te da una intuición precisa de por qué el compilador acepta o rechaza una asignación.&lt;/p&gt;
&lt;p&gt;En el siguiente artículo aplicaremos metaprogramación con &lt;strong&gt;decoradores&lt;/strong&gt;, funciones que extienden el comportamiento de clases, métodos y propiedades.&lt;/p&gt;</content:encoded></item><item><title>TypeScript: Tipos básicos y el sistema de tipos</title><link>https://blog.dacadev.com/typescript/tipos-basicos/</link><pubDate>Mon, 15 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/typescript/tipos-basicos/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Domina los tipos básicos de TypeScript: any, unknown, boolean, number, bigint, string, symbol, objetos, alias, uniones, intersecciones, arreglos y tuplas.</description><media:content url="https://blog.dacadev.com/images/typescript/basic-types/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#por-qué-importan-los-tipos-un-ejemplo-concreto"&gt;Por qué importan los tipos: un ejemplo concreto&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#any-la-puerta-de-escape-del-sistema-de-tipos"&gt;any: la puerta de escape del sistema de tipos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#unknown-la-alternativa-segura-a-any"&gt;unknown: la alternativa segura a any&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#boolean"&gt;boolean&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#number-y-bigint"&gt;number y bigint&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#string"&gt;string&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#symbol"&gt;symbol&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#objetos"&gt;Objetos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#alias-de-tipo"&gt;Alias de tipo&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#tipos-unión-e-intersección"&gt;Tipos unión e intersección&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#arreglos"&gt;Arreglos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#tuplas"&gt;Tuplas&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Segundo artículo de la serie sobre &lt;strong&gt;TypeScript&lt;/strong&gt;. Recorreremos el alfabeto de tipos del lenguaje: desde &lt;code&gt;any&lt;/code&gt; y &lt;code&gt;unknown&lt;/code&gt; hasta uniones, intersecciones, tuplas y alias de tipo.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Cuando el typechecker sabe que un valor es de tipo &lt;code&gt;T&lt;/code&gt;, no solo conoce su naturaleza: también sabe &lt;strong&gt;exactamente qué operaciones son válidas&lt;/strong&gt; sobre ese valor y cuáles no. Ese es el propósito del sistema de tipos. Comprender el catálogo de &lt;strong&gt;tipos básicos en TypeScript&lt;/strong&gt; es la base sobre la que se construye todo lo demás, así que dediquémosle la atención que merece.&lt;/p&gt;
&lt;h2 id="por-qué-importan-los-tipos-un-ejemplo-concreto"&gt;Por qué importan los tipos: un ejemplo concreto&lt;/h2&gt;
&lt;p&gt;Los tipos transmiten intención de forma explícita y verificable. Comparemos la misma función en JavaScript y en TypeScript:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// JavaScript
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;squareOf&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;n&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt; &lt;span style="color:#e06c75"&gt;n&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;squareOf&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;2&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// 4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;squareOf&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;z&amp;#39;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// NaN — falla en silencio
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// TypeScript
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;squareOf&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;n&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt; &lt;span style="color:#e06c75"&gt;n&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;squareOf&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;2&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// 4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;squareOf&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;z&amp;#39;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// Error TS2345: el argumento de tipo &amp;#39;string&amp;#39; no es
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;// asignable al parámetro de tipo &amp;#39;number&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En JavaScript, &lt;code&gt;squareOf('z')&lt;/code&gt; devuelve &lt;code&gt;NaN&lt;/code&gt; sin protestar y el error se propaga aguas abajo. En TypeScript el compilador lo intercepta en el sitio exacto donde se cometió.&lt;/p&gt;
&lt;h2 id="any-la-puerta-de-escape-del-sistema-de-tipos"&gt;any: la puerta de escape del sistema de tipos&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;any&lt;/code&gt; indica que una variable puede contener cualquier tipo de dato. Desactiva por completo la verificación:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;avenger&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;any&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;123&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;avenger&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;Dr. Strange&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;((&lt;span style="color:#e06c75"&gt;avenger&lt;/span&gt; &lt;span style="color:#c678dd"&gt;as&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;).&lt;span style="color:#e06c75"&gt;charAt&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;avenger&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;15.23425&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;((&amp;lt;&lt;span style="color:#e06c75"&gt;number&lt;/span&gt;&amp;gt;&lt;span style="color:#e06c75"&gt;avenger&lt;/span&gt;).&lt;span style="color:#e06c75"&gt;toFixed&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;2&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Cuando usas &lt;code&gt;any&lt;/code&gt;, el typechecker deja de ayudarte. Puedes reorientarlo mediante un &lt;em&gt;cast&lt;/em&gt; —indicar manualmente qué tipo debe asumir en un punto dado— con la sintaxis &lt;code&gt;(variable as Tipo)&lt;/code&gt; o &lt;code&gt;&amp;lt;Tipo&amp;gt;variable&lt;/code&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Evita &lt;code&gt;any&lt;/code&gt; salvo en migraciones puntuales o fronteras con código sin tipado. Cada &lt;code&gt;any&lt;/code&gt; es un agujero por el que se filtran errores que el compilador debería haber detenido.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="unknown-la-alternativa-segura-a-any"&gt;unknown: la alternativa segura a any&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;unknown&lt;/code&gt; es el primo responsable de &lt;code&gt;any&lt;/code&gt;. Acepta cualquier valor, pero &lt;strong&gt;TypeScript prohíbe operar sobre él&lt;/strong&gt; hasta que acotes su tipo mediante una comprobación. Esto añade una capa de seguridad: sí admite operaciones de comparación e identidad (&lt;code&gt;==&lt;/code&gt;, &lt;code&gt;===&lt;/code&gt;, &lt;code&gt;||&lt;/code&gt;, &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, el operador ternario &lt;code&gt;?&lt;/code&gt;) y negación con &lt;code&gt;!&lt;/code&gt;, pero no el acceso a propiedades arbitrarias.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;dato&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;unknown&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;obtenerValor&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// dato.toFixed(2) // Error: &amp;#39;dato&amp;#39; es de tipo &amp;#39;unknown&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;if&lt;/span&gt; (&lt;span style="color:#c678dd"&gt;typeof&lt;/span&gt; &lt;span style="color:#e06c75"&gt;dato&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;===&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;number&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;dato&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;toFixed&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;2&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// OK: dentro del guard, dato es number
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Usa &lt;code&gt;unknown&lt;/code&gt; siempre que recibas datos externos (respuestas de API, entrada del usuario) en lugar de &lt;code&gt;any&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="boolean"&gt;boolean&lt;/h2&gt;
&lt;p&gt;Acepta las operaciones &lt;code&gt;==&lt;/code&gt;, &lt;code&gt;===&lt;/code&gt;, &lt;code&gt;||&lt;/code&gt;, &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, el ternario &lt;code&gt;?&lt;/code&gt; y la negación &lt;code&gt;!&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// boolean
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;c&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// true (tipo literal)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;d&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;boolean&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// boolean
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;e&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// true
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;f&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;false&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// Error TS2322: &amp;#39;false&amp;#39; no es asignable a &amp;#39;true&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;El tipo &lt;code&gt;true&lt;/code&gt; (literal) es más restrictivo que &lt;code&gt;boolean&lt;/code&gt;: además de exigir un booleano, exige que su valor sea exactamente &lt;code&gt;true&lt;/code&gt;. Los &lt;strong&gt;tipos literales&lt;/strong&gt; son una herramienta poderosa para modelar estados precisos.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="number-y-bigint"&gt;number y bigint&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;number&lt;/code&gt; cubre enteros, flotantes, &lt;code&gt;Infinity&lt;/code&gt;, &lt;code&gt;NaN&lt;/code&gt; y valores positivos y negativos:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1234&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// number
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;c&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;5678&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 5678 (literal)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;e&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;100&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// number
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;f&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;26.218&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;26.218&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 26.218 (literal)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;g&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;26.218&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;10&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// Error TS2322
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Un &lt;code&gt;number&lt;/code&gt; representa con precisión hasta 2^53. Para enteros mayores existe &lt;code&gt;bigint&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1234&lt;/span&gt;&lt;span style="color:#e06c75"&gt;n&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// bigint
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;b&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;5678&lt;/span&gt;&lt;span style="color:#e06c75"&gt;n&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 5678n
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;e&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;88.5&lt;/span&gt;&lt;span style="color:#e06c75"&gt;n&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// Error TS1353: un literal bigint debe ser entero.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;h&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;bigint&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;100&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// Error TS2322: &amp;#39;100&amp;#39; no es asignable a &amp;#39;bigint&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="string"&gt;string&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;hello&amp;#39;&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// string
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;c&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;!&amp;#39;&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// &amp;#39;!&amp;#39; (literal)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;e&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;zoom&amp;#39;&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// string
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;f&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;john&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;john&amp;#39;&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// &amp;#39;john&amp;#39; (literal)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;g&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;john&amp;#39;&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;zoe&amp;#39;&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// Error TS2322
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="symbol"&gt;symbol&lt;/h2&gt;
&lt;p&gt;Un &lt;code&gt;symbol&lt;/code&gt; representa un identificador único. Se crea con &lt;code&gt;Symbol()&lt;/code&gt; y admite una descripción opcional útil para depurar:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;id&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Symbol&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;); &lt;span style="color:#7f848e"&gt;// symbol con descripción &amp;#34;id&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La garantía clave: &lt;strong&gt;dos símbolos nunca son iguales&lt;/strong&gt;, aunque compartan descripción. La descripción es solo una etiqueta sin efecto sobre la identidad.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;id1&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Symbol&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;id2&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Symbol&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;id1&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;===&lt;/span&gt; &lt;span style="color:#e06c75"&gt;id2&lt;/span&gt;); &lt;span style="color:#7f848e"&gt;// false
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;d&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;id1&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;x&amp;#39;&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// Error TS2469: el operador &amp;#39;+&amp;#39; no aplica a &amp;#39;symbol&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="objetos"&gt;Objetos&lt;/h2&gt;
&lt;p&gt;Hay dos formas de tipar objetos. La primera usa la palabra clave &lt;code&gt;object&lt;/code&gt;, que solo garantiza que el valor no es &lt;code&gt;null&lt;/code&gt; pero &lt;strong&gt;no expone sus propiedades&lt;/strong&gt;, porque TypeScript no sabe qué objeto es:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;object&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;x&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// a.b // Error: la propiedad &amp;#39;b&amp;#39; no existe en el tipo &amp;#39;object&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La segunda —y recomendada— describe la forma exacta del objeto:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;c&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;firstName&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;lastName&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;firstName&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;john&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;lastName&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;barrowman&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Las definiciones de objeto admiten campos opcionales (&lt;code&gt;?&lt;/code&gt;), índices dinámicos y propiedades de solo lectura:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// obligatorio, number
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;c?&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// opcional, string
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#e06c75"&gt;key&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;]&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;boolean&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// cualquier clave numérica → boolean
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;user&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;readonly&lt;/span&gt; &lt;span style="color:#e06c75"&gt;firstName&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;firstName&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;abby&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;user&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;firstName&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;abbey&amp;#39;&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// Error TS2540: propiedad de solo lectura.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Evita tipar con el objeto vacío &lt;code&gt;{}&lt;/code&gt;. Acepta cualquier valor distinto de &lt;code&gt;null&lt;/code&gt; o &lt;code&gt;undefined&lt;/code&gt; (incluso números o arreglos), lo que vacía de sentido la anotación.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="alias-de-tipo"&gt;Alias de tipo&lt;/h2&gt;
&lt;p&gt;Los alias asignan un nombre semántico a un tipo, mejorando la legibilidad sin alterar la verificación:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Age&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Person&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Age&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;driver&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Person&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;James May&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;55&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Como &lt;code&gt;Age&lt;/code&gt; es solo un alias de &lt;code&gt;number&lt;/code&gt;, sigue siendo compatible con cualquier &lt;code&gt;number&lt;/code&gt;. Ten presente que un alias &lt;strong&gt;solo puede declararse una vez&lt;/strong&gt; por ámbito; aplica las mismas reglas de &lt;em&gt;shadowing&lt;/em&gt; que &lt;code&gt;let&lt;/code&gt;, &lt;code&gt;const&lt;/code&gt; y &lt;code&gt;var&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="tipos-unión-e-intersección"&gt;Tipos unión e intersección&lt;/h2&gt;
&lt;p&gt;Recurriendo a la teoría de conjuntos: la &lt;strong&gt;unión&lt;/strong&gt; (&lt;code&gt;|&lt;/code&gt;) admite uno u otro tipo —o ambos—, mientras que la &lt;strong&gt;intersección&lt;/strong&gt; (&lt;code&gt;&amp;amp;&lt;/code&gt;) exige cumplir simultáneamente todas las formas combinadas.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 subgraph Union[&amp;#34;A | B&amp;#34;]
 U[Cualquier valor que sea A, B o ambos]
 end
 subgraph Inter[&amp;#34;A &amp;amp; B&amp;#34;]
 I[Solo valores que cumplen A y B a la vez]
 end
&lt;/pre&gt;

&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Cat&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;purrs&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;boolean&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Dog&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;name&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;barks&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;boolean&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;wags&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;boolean&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;CatOrDogOrBoth&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Cat&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Dog&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// unión
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;CatAndDog&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Cat&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;amp;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Dog&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// intersección
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Un valor &lt;code&gt;Cat | Dog&lt;/code&gt; puede ser un gato, un perro o un objeto que cumpla ambas formas. Un valor &lt;code&gt;Cat &amp;amp; Dog&lt;/code&gt;, en cambio, está obligado a tener &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;purrs&lt;/code&gt;, &lt;code&gt;barks&lt;/code&gt; y &lt;code&gt;wags&lt;/code&gt; al mismo tiempo.&lt;/p&gt;
&lt;h2 id="arreglos"&gt;Arreglos&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;// number[]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;d&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;// (string | number)[]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;h&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;[] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;h&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;push&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// OK
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;h&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;push&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;red&amp;#39;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// Error TS2345
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Un arreglo declarado vacío sin anotación arranca como &lt;code&gt;any[]&lt;/code&gt; y va ampliando su tipo según lo que insertes —otra razón para anotar explícitamente las colecciones en las fronteras del sistema.&lt;/p&gt;
&lt;h2 id="tuplas"&gt;Tuplas&lt;/h2&gt;
&lt;p&gt;Las tuplas son un subconjunto de los arreglos con &lt;strong&gt;longitud fija&lt;/strong&gt; y tipos posicionales:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; [&lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// [nombre, apellido, año de nacimiento]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; [&lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#39;malcolm&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;gladwell&amp;#39;&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;1963&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;b&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#39;queen&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;elizabeth&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;ii&amp;#39;&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;1926&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;// Error TS2322: posición/longitud inválida
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;También admiten posiciones opcionales:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Tarifas de tren que a veces varían según la dirección
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;trainFares&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; [&lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;?&lt;/span&gt;][] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#d19a66"&gt;3.75&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#d19a66"&gt;8.25&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;7.70&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [&lt;span style="color:#d19a66"&gt;10.50&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;El sistema de tipos de TypeScript va mucho más allá de etiquetar variables: distingue entre &lt;code&gt;any&lt;/code&gt; (inseguro) y &lt;code&gt;unknown&lt;/code&gt; (seguro), modela estados exactos con tipos literales, compone formas mediante uniones e intersecciones y garantiza estructuras rígidas con tuplas. Dominar este catálogo es el prerrequisito para los temas avanzados de la serie.&lt;/p&gt;
&lt;p&gt;En el siguiente artículo aplicaremos estos fundamentos a los &lt;strong&gt;objetos y tipos personalizados&lt;/strong&gt;, donde los alias de tipo se vuelven el centro del diseño.&lt;/p&gt;</content:encoded></item><item><title>Estilos CSS: Selectores, combinadores y pseudo-clases</title><link>https://blog.dacadev.com/programacion/estilos-css/selectores-css/</link><pubDate>Thu, 04 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/estilos-css/selectores-css/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Aprende a apuntar a cualquier elemento con los selectores de CSS: básicos, combinadores, pseudo-clases, pseudo-elementos y selectores de atributo, con ejemplos en vivo.</description><media:content url="https://blog.dacadev.com/images/programming/html-and-css/css/02-selectores-css-banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#selectores-básicos"&gt;Selectores básicos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#combinadores"&gt;Combinadores&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#selectores-compuestos"&gt;Selectores compuestos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#pseudo-clases"&gt;Pseudo-clases&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#posición-estructural"&gt;Posición estructural&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#estado-e-interacción"&gt;Estado e interacción&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#campos-de-formulario"&gt;Campos de formulario&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#pseudo-elementos"&gt;Pseudo-elementos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#selectores-de-atributo"&gt;Selectores de atributo&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Un selector es el mecanismo con el que CSS apunta a los elementos que vas a estilizar. Elegir el selector correcto no es solo cuestión de que &amp;ldquo;funcione&amp;rdquo;: impacta directamente en la especificidad, en el acoplamiento de tus estilos y en la facilidad para mantenerlos. CSS ofrece un catálogo amplio de selectores, y conocerlos a fondo te evita escribir reglas frágiles.&lt;/p&gt;
&lt;p&gt;Este artículo es la segunda entrega de la serie &lt;strong&gt;Estilos CSS&lt;/strong&gt;. Recorreremos los selectores básicos, los combinadores, las pseudo-clases, los pseudo-elementos y los selectores de atributo, con ejemplos que puedes ver renderizados aquí mismo.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Repasaremos cada familia de selectores con su especificidad y demostraciones en vivo, para que puedas elegir siempre la opción más precisa y de menor acoplamiento.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="selectores-básicos"&gt;Selectores básicos&lt;/h2&gt;
&lt;p&gt;Son los cuatro selectores fundamentales sobre los que se construye todo lo demás:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Selector de tipo&lt;/strong&gt; (&lt;code&gt;p&lt;/code&gt;, &lt;code&gt;h1&lt;/code&gt;) — apunta por nombre de etiqueta. Especificidad &lt;code&gt;0,0,1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Selector de clase&lt;/strong&gt; (&lt;code&gt;.media&lt;/code&gt;) — apunta a los elementos con esa clase. Especificidad &lt;code&gt;0,1,0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Selector de ID&lt;/strong&gt; (&lt;code&gt;#sidebar&lt;/code&gt;) — apunta al elemento con ese &lt;code&gt;id&lt;/code&gt;. Especificidad &lt;code&gt;1,0,0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Selector universal&lt;/strong&gt; (&lt;code&gt;*&lt;/code&gt;) — apunta a todos los elementos. Especificidad &lt;code&gt;0,0,0&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="combinadores"&gt;Combinadores&lt;/h2&gt;
&lt;p&gt;Los &lt;strong&gt;combinadores&lt;/strong&gt; unen selectores simples para describir una relación entre elementos.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Combinador&lt;/th&gt;
 &lt;th&gt;Símbolo&lt;/th&gt;
 &lt;th&gt;Significado&lt;/th&gt;
 &lt;th&gt;Ejemplo&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Descendiente&lt;/td&gt;
 &lt;td&gt;(espacio)&lt;/td&gt;
 &lt;td&gt;Cualquier descendiente&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;.menu li&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Hijo directo&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;&amp;gt;&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Hijo inmediato&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;.lista &amp;gt; li&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Hermano adyacente&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;+&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;El elemento inmediatamente siguiente&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;p + h2&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Hermano general&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;~&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Todos los hermanos posteriores&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;li.activo ~ li&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;El combinador de hijo directo (&lt;code&gt;&amp;gt;&lt;/code&gt;) solo afecta al primer nivel de descendientes. Observa la diferencia con el descendiente:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;lista&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;li&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-weight&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;bold&lt;/span&gt;; } &lt;span style="color:#7f848e"&gt;/* solo hijos directos */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;ul&lt;/span&gt; &lt;span style="color:#e06c75"&gt;class&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;lista&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#e06c75"&gt;li&lt;/span&gt;&amp;gt;Hijo directo (en negrita)&amp;lt;/&lt;span style="color:#e06c75"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#e06c75"&gt;li&lt;/span&gt;&amp;gt;Hijo directo (en negrita)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#e06c75"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#e06c75"&gt;li&lt;/span&gt;&amp;gt;Nieto (sin negrita)&amp;lt;/&lt;span style="color:#e06c75"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#e06c75"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/&lt;span style="color:#e06c75"&gt;li&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#e06c75"&gt;ul&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem 1.25rem;background:#fff;color:#111;margin:1rem 0;"&gt;
 &lt;style&gt;
 .cssel-child &gt; li { font-weight:bold; }
 .cssel-child ul li { font-weight:normal; }
 .cssel-child, .cssel-child ul { font-family:Helvetica,Arial,sans-serif; }
 &lt;/style&gt;
 &lt;ul class="cssel-child"&gt;
 &lt;li&gt;Hijo directo (en negrita)&lt;/li&gt;
 &lt;li&gt;Hijo directo (en negrita)
 &lt;ul&gt;
 &lt;li&gt;Nieto (sin negrita)&lt;/li&gt;
 &lt;/ul&gt;
 &lt;/li&gt;
 &lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id="selectores-compuestos"&gt;Selectores compuestos&lt;/h2&gt;
&lt;p&gt;Varios selectores simples se pueden unir &lt;strong&gt;sin espacios&lt;/strong&gt; para formar un selector compuesto que exige que el elemento cumpla &lt;em&gt;todas&lt;/em&gt; las condiciones. Por ejemplo, &lt;code&gt;.dropdown.is-active&lt;/code&gt; apunta a &lt;code&gt;&amp;lt;div class=&amp;quot;dropdown is-active&amp;quot;&amp;gt;&lt;/code&gt; pero no a &lt;code&gt;&amp;lt;div class=&amp;quot;dropdown&amp;quot;&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="pseudo-clases"&gt;Pseudo-clases&lt;/h2&gt;
&lt;p&gt;Las &lt;strong&gt;pseudo-clases&lt;/strong&gt; apuntan a elementos según un estado: interacción del usuario o posición respecto a sus hermanos. Empiezan con un solo dos puntos (&lt;code&gt;:&lt;/code&gt;) y tienen la especificidad de una clase (&lt;code&gt;0,1,0&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id="posición-estructural"&gt;Posición estructural&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:first-child&lt;/code&gt;, &lt;code&gt;:last-child&lt;/code&gt;, &lt;code&gt;:only-child&lt;/code&gt; — primero, último o único hijo.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:nth-child(an + b)&lt;/code&gt; — apunta según una fórmula posicional entre sus hermanos.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:nth-last-child()&lt;/code&gt; — igual, pero contando desde el final.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:first-of-type&lt;/code&gt;, &lt;code&gt;:last-of-type&lt;/code&gt;, &lt;code&gt;:nth-of-type()&lt;/code&gt; — equivalentes, pero solo cuentan elementos del mismo tipo.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:not(&amp;lt;selector&amp;gt;)&lt;/code&gt; — apunta a lo que &lt;em&gt;no&lt;/em&gt; coincide con el selector interno.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:empty&lt;/code&gt; — elementos sin hijos.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Un patrón clásico: aplicar un fondo alterno con &lt;code&gt;:nth-child(even)&lt;/code&gt; para crear filas tipo &amp;ldquo;cebra&amp;rdquo;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;zebra&lt;/span&gt; &lt;span style="color:#e06c75"&gt;li&lt;/span&gt;:&lt;span style="color:#61afef"&gt;nth-child&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;even&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;background&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#ecf0f1&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem 1.25rem;background:#fff;color:#111;margin:1rem 0;"&gt;
 &lt;style&gt;
 .cssel-zebra { list-style:none;padding:0;margin:0;font-family:Helvetica,Arial,sans-serif; }
 .cssel-zebra li { padding:.5em .75em; }
 .cssel-zebra li:nth-child(even) { background:#ecf0f1; }
 &lt;/style&gt;
 &lt;ul class="cssel-zebra"&gt;
 &lt;li&gt;Fila 1&lt;/li&gt;
 &lt;li&gt;Fila 2 (resaltada)&lt;/li&gt;
 &lt;li&gt;Fila 3&lt;/li&gt;
 &lt;li&gt;Fila 4 (resaltada)&lt;/li&gt;
 &lt;/ul&gt;
&lt;/div&gt;
&lt;h3 id="estado-e-interacción"&gt;Estado e interacción&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:hover&lt;/code&gt; — mientras el cursor está sobre el elemento.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:focus&lt;/code&gt; — cuando el elemento recibe foco (clic, toque o tabulación).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:root&lt;/code&gt; — el elemento raíz del documento.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="campos-de-formulario"&gt;Campos de formulario&lt;/h3&gt;
&lt;p&gt;Varias pseudo-clases describen el estado de los controles: &lt;code&gt;:disabled&lt;/code&gt;, &lt;code&gt;:enabled&lt;/code&gt;, &lt;code&gt;:checked&lt;/code&gt;, &lt;code&gt;:invalid&lt;/code&gt;, &lt;code&gt;:valid&lt;/code&gt;, &lt;code&gt;:required&lt;/code&gt;, &lt;code&gt;:optional&lt;/code&gt;. Aquí, &lt;code&gt;:invalid&lt;/code&gt; cambia el borde cuando el valor no es un correo válido:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;input&lt;/span&gt;:&lt;span style="color:#61afef"&gt;invalid&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;border-color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#c0392b&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;input&lt;/span&gt;:&lt;span style="color:#61afef"&gt;valid&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;border-color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#27ae60&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem 1.25rem;background:#fff;color:#111;margin:1rem 0;"&gt;
 &lt;style&gt;
 .cssel-form input { padding:.5em;border:2px solid #ccc;border-radius:.3em;font-size:1rem;font-family:Helvetica,Arial,sans-serif; }
 .cssel-form input:invalid { border-color:#c0392b; }
 .cssel-form input:valid { border-color:#27ae60; }
 &lt;/style&gt;
 &lt;div class="cssel-form"&gt;
 &lt;label&gt;Escribe un correo: &lt;input type="email" placeholder="tu@correo.com" required&gt;&lt;/label&gt;
 &lt;/div&gt;
&lt;/div&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;La lista de pseudo-clases es extensa y evoluciona con cada nivel de la especificación. Consulta la &lt;a href="https://developer.mozilla.org/es/docs/Web/CSS/Pseudo-classes"




 target="_blank"
 


&gt;documentación de MDN sobre pseudo-clases&lt;/a&gt; para el catálogo completo y el soporte por navegador.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="pseudo-elementos"&gt;Pseudo-elementos&lt;/h2&gt;
&lt;p&gt;Los &lt;strong&gt;pseudo-elementos&lt;/strong&gt; no apuntan a un elemento existente, sino a una parte del documento que no tiene marcado propio, o inyectan contenido nuevo. Usan doble dos puntos (&lt;code&gt;::&lt;/code&gt;) y tienen la especificidad de un selector de tipo (&lt;code&gt;0,0,1&lt;/code&gt;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;::before&lt;/code&gt; — inserta un primer hijo virtual. Requiere la propiedad &lt;code&gt;content&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;::after&lt;/code&gt; — inserta un último hijo virtual. Requiere &lt;code&gt;content&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;::first-letter&lt;/code&gt; — estiliza la primera letra del texto.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;::first-line&lt;/code&gt; — estiliza la primera línea.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;::selection&lt;/code&gt; — estiliza el texto que el usuario resalta.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;nota&lt;/span&gt;::&lt;span style="color:#61afef"&gt;before&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;content&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;★ &amp;#34;&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#f39c12&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;capitular&lt;/span&gt;::&lt;span style="color:#61afef"&gt;first-letter&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-size&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;2.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;font-weight&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;bold&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#2a9da9&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem 1.25rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;p style="margin:.2rem 0;"&gt;&lt;span style="color:#f39c12;"&gt;★ &lt;/span&gt;Texto precedido por un pseudo-elemento &lt;code&gt;::before&lt;/code&gt;.&lt;/p&gt;
 &lt;p style="margin:.6rem 0 0;"&gt;&lt;span style="font-size:2.5em;font-weight:bold;color:#2a9da9;"&gt;L&lt;/span&gt;orem ipsum con la primera letra estilizada como capitular.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="selectores-de-atributo"&gt;Selectores de atributo&lt;/h2&gt;
&lt;p&gt;Apuntan a elementos según sus atributos HTML. Tienen la especificidad de una clase (&lt;code&gt;0,1,0&lt;/code&gt;).&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Selector&lt;/th&gt;
 &lt;th&gt;Coincide cuando el atributo&amp;hellip;&lt;/th&gt;
 &lt;th&gt;Ejemplo&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;[attr]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;existe&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;input[disabled]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;[attr=&amp;quot;valor&amp;quot;]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;es exactamente igual&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;input[type=&amp;quot;radio&amp;quot;]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;[attr^=&amp;quot;valor&amp;quot;]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;empieza con el valor&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;a[href^=&amp;quot;https&amp;quot;]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;[attr$=&amp;quot;valor&amp;quot;]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;termina con el valor&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;a[href$=&amp;quot;.pdf&amp;quot;]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;[attr*=&amp;quot;valor&amp;quot;]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;contiene el valor&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[class*=&amp;quot;sprite-&amp;quot;]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;[attr~=&amp;quot;valor&amp;quot;]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;es una lista separada por espacios que incluye el valor&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;a[rel~=&amp;quot;author&amp;quot;]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;[attr|=&amp;quot;valor&amp;quot;]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;es igual o empieza con &lt;code&gt;valor-&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[lang|=&amp;quot;es&amp;quot;]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Por ejemplo, podemos marcar visualmente los enlaces externos y los que apuntan a un PDF:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;[&lt;/span&gt;&lt;span style="color:#e06c75"&gt;href&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;^=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;https&amp;#34;&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;]&lt;/span&gt;::&lt;span style="color:#61afef"&gt;after&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;content&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34; ↗&amp;#34;&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;[&lt;/span&gt;&lt;span style="color:#e06c75"&gt;href&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;$=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;.pdf&amp;#34;&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;]&lt;/span&gt;::&lt;span style="color:#61afef"&gt;after&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;content&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34; (PDF)&amp;#34;&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#c0392b&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem 1.25rem;background:#fff;color:#111;margin:1rem 0;font-family:Helvetica,Arial,sans-serif;"&gt;
 &lt;p style="margin:0;"&gt;
 &lt;a href="https://developer.mozilla.org" style="color:#2a7ae2;"&gt;Enlace externo&lt;span style="color:#2a7ae2;"&gt; ↗&lt;/span&gt;&lt;/a&gt; ·
 &lt;a href="#" style="color:#2a7ae2;"&gt;Documento&lt;span style="color:#c0392b;"&gt; (PDF)&lt;/span&gt;&lt;/a&gt;
 &lt;/p&gt;
&lt;/div&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Los selectores de atributo distinguen mayúsculas y minúsculas por defecto. La especificación nivel 4 añade un modificador &lt;code&gt;i&lt;/code&gt; antes del corchete de cierre —&lt;code&gt;input[value=&amp;quot;search&amp;quot; i]&lt;/code&gt;— para hacerlos insensibles a mayúsculas. Verifica el soporte antes de usarlo en producción.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;El catálogo de selectores de CSS es amplio y cada familia resuelve un problema distinto. La clave está en elegir el selector más preciso con la menor especificidad posible: eso mantiene tus estilos desacoplados y fáciles de sobrescribir cuando lo necesites.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 En la siguiente entrega abordamos el &lt;strong&gt;modelo de caja&lt;/strong&gt;: cómo &lt;code&gt;margin&lt;/code&gt;, &lt;code&gt;border&lt;/code&gt;, &lt;code&gt;padding&lt;/code&gt; y &lt;code&gt;content&lt;/code&gt; definen el tamaño real de cada elemento y cómo &lt;code&gt;box-sizing&lt;/code&gt; cambia las reglas del juego.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>Estilos CSS: Cascada, especificidad, herencia y unidades</title><link>https://blog.dacadev.com/programacion/estilos-css/fundamentos-cascada-especificidad-herencia/</link><pubDate>Tue, 02 Jun 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/estilos-css/fundamentos-cascada-especificidad-herencia/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Domina los fundamentos de CSS: cómo resuelve el navegador los conflictos de estilos con la cascada, la especificidad, la herencia y las unidades em, rem y vw.</description><media:content url="https://blog.dacadev.com/images/programming/html-and-css/css/01-fundamentos-cascada-especificidad-herencia-banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#la-cascada-cómo-el-navegador-resuelve-conflictos"&gt;La cascada: cómo el navegador resuelve conflictos&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#origen-de-los-estilos"&gt;Origen de los estilos&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#especificidad-el-peso-de-un-selector"&gt;Especificidad: el peso de un selector&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#orden-del-código-el-último-en-hablar-gana"&gt;Orden del código: el último en hablar gana&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#herencia-propiedades-que-viajan-hacia-abajo"&gt;Herencia: propiedades que viajan hacia abajo&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#valores-especiales-inherit-e-initial"&gt;Valores especiales: &lt;code&gt;inherit&lt;/code&gt; e &lt;code&gt;initial&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#unidades-absolutas-vs-relativas"&gt;Unidades absolutas vs. relativas&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#em-relativo-al-elemento"&gt;&lt;code&gt;em&lt;/code&gt;: relativo al elemento&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#rem-relativo-a-la-raíz"&gt;&lt;code&gt;rem&lt;/code&gt;: relativo a la raíz&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#unidades-relativas-al-viewport"&gt;Unidades relativas al viewport&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#calc-para-combinar-unidades"&gt;&lt;code&gt;calc()&lt;/code&gt; para combinar unidades&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#números-sin-unidad-y-line-height"&gt;Números sin unidad y &lt;code&gt;line-height&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#custom-properties-variables-css"&gt;Custom properties (variables CSS)&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#redefinir-variables-por-contexto"&gt;Redefinir variables por contexto&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Cuando dos reglas de estilo compiten por el mismo elemento, el resultado no es aleatorio: el navegador aplica un algoritmo determinista para decidir cuál gana. Comprender ese algoritmo —la cascada, la especificidad y la herencia— es la diferencia entre pelear contra CSS a punta de &lt;code&gt;!important&lt;/code&gt; y escribir hojas de estilo predecibles y mantenibles.&lt;/p&gt;
&lt;p&gt;Este artículo abre la serie &lt;strong&gt;Estilos CSS&lt;/strong&gt;. Analizaremos cómo el navegador resuelve conflictos, cómo se calcula el peso de un selector y cómo aprovechar las unidades relativas para construir interfaces que escalan.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Al terminar entenderás el modelo mental que rige &lt;em&gt;toda&lt;/em&gt; hoja de estilos: origen de los estilos, especificidad, orden del código, herencia y el sistema de unidades relativas (&lt;code&gt;em&lt;/code&gt;, &lt;code&gt;rem&lt;/code&gt;, &lt;code&gt;vw&lt;/code&gt;) junto con las variables CSS.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="la-cascada-cómo-el-navegador-resuelve-conflictos"&gt;La cascada: cómo el navegador resuelve conflictos&lt;/h2&gt;
&lt;p&gt;CSS significa &lt;em&gt;Cascading Style Sheets&lt;/em&gt;. La &lt;strong&gt;cascada&lt;/strong&gt; es precisamente el conjunto de reglas que determina qué declaración prevalece cuando varias apuntan a la misma propiedad de un elemento. El navegador evalúa tres criterios en orden:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Origen de la hoja de estilos&lt;/strong&gt; — de dónde provienen los estilos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Especificidad del selector&lt;/strong&gt; — qué selector es más &amp;ldquo;específico&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Orden en el código&lt;/strong&gt; — cuál se declaró de último.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="origen-de-los-estilos"&gt;Origen de los estilos&lt;/h3&gt;
&lt;p&gt;Existen tres orígenes posibles, con prioridad creciente:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;User agent styles&lt;/strong&gt; — los estilos por defecto del navegador (por ejemplo, el &lt;code&gt;margin&lt;/code&gt; de un &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; o el subrayado de un enlace).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Author styles&lt;/strong&gt; — los estilos que tú defines en tus archivos &lt;code&gt;.css&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User styles&lt;/strong&gt; — estilos configurados por el propio usuario en el navegador (accesibilidad, tamaños de fuente). Tienen prioridad sobre los anteriores.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tus estilos (&lt;em&gt;author&lt;/em&gt;) pisan a los del navegador, que es justo lo que esperas al escribir una hoja de estilos.&lt;/p&gt;
&lt;h2 id="especificidad-el-peso-de-un-selector"&gt;Especificidad: el peso de un selector&lt;/h2&gt;
&lt;p&gt;La &lt;strong&gt;especificidad&lt;/strong&gt; se representa con la notación &lt;code&gt;0,0,0,0&lt;/code&gt;, donde cada posición cuenta, de izquierda a derecha: estilos &lt;em&gt;inline&lt;/em&gt;, IDs, clases y nombres de etiqueta.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Componente&lt;/th&gt;
 &lt;th&gt;Ejemplo&lt;/th&gt;
 &lt;th&gt;Peso&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Selector de etiqueta&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;p&lt;/code&gt;, &lt;code&gt;h1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;0,0,0,1&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Selector de clase&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;.nav-menu&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;0,0,1,0&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Selector de ID&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;#sidebar&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;0,1,0,0&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Estilo inline&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;style=&amp;quot;...&amp;quot;&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;1,0,0,0&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Las reglas de desempate son sencillas:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Una declaración con &lt;code&gt;!important&lt;/code&gt; gana por encima de todo (úsala con prudencia).&lt;/li&gt;
&lt;li&gt;Gana el selector con más IDs.&lt;/li&gt;
&lt;li&gt;Si hay empate, gana el que tenga más clases.&lt;/li&gt;
&lt;li&gt;Si persiste el empate, gana el que tenga más etiquetas.&lt;/li&gt;
&lt;/ol&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Las pseudo-clases (&lt;code&gt;:hover&lt;/code&gt;) y los selectores de atributo (&lt;code&gt;[type=&amp;quot;text&amp;quot;]&lt;/code&gt;) cuentan como una clase (&lt;code&gt;0,0,1,0&lt;/code&gt;). El selector universal &lt;code&gt;*&lt;/code&gt; y los combinadores (&lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;~&lt;/code&gt;) &lt;strong&gt;no&lt;/strong&gt; aportan especificidad.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Observa cómo dos reglas compiten por el color del párrafo. La clase &lt;code&gt;.destacado&lt;/code&gt; gana al selector de etiqueta &lt;code&gt;p&lt;/code&gt;, aunque la regla de &lt;code&gt;p&lt;/code&gt; se declare después:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;p&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#555&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;destacado&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#c0392b&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;p&lt;/span&gt;&amp;gt;Texto con el color por defecto del selector de etiqueta.&amp;lt;/&lt;span style="color:#e06c75"&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;p&lt;/span&gt; &lt;span style="color:#e06c75"&gt;class&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;destacado&amp;#34;&lt;/span&gt;&amp;gt;Este párrafo gana por especificidad de clase.&amp;lt;/&lt;span style="color:#e06c75"&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem 1.25rem;background:#fff;color:#111;margin:1rem 0;"&gt;
 &lt;style&gt;
 .csfund-spec p { color:#555;margin:.25rem 0;font-family:Helvetica,Arial,sans-serif; }
 .csfund-spec .destacado { color:#c0392b;font-weight:bold; }
 &lt;/style&gt;
 &lt;div class="csfund-spec"&gt;
 &lt;p&gt;Texto con el color por defecto del selector de etiqueta.&lt;/p&gt;
 &lt;p class="destacado"&gt;Este párrafo gana por especificidad de clase.&lt;/p&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="orden-del-código-el-último-en-hablar-gana"&gt;Orden del código: el último en hablar gana&lt;/h2&gt;
&lt;p&gt;Cuando dos declaraciones tienen el &lt;strong&gt;mismo origen y la misma especificidad&lt;/strong&gt;, el navegador aplica la que aparece de última en el código fuente. Este comportamiento es crítico al ordenar las pseudo-clases de un enlace.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;:&lt;span style="color:#61afef"&gt;link&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#2a7ae2&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;:&lt;span style="color:#61afef"&gt;visited&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#8e44ad&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;:&lt;span style="color:#61afef"&gt;hover&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;text-decoration&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;underline&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;:&lt;span style="color:#61afef"&gt;active&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#c0392b&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Como las cuatro pseudo-clases tienen la misma especificidad, su orden importa. La regla mnemotécnica es &lt;strong&gt;LoVe/HAte&lt;/strong&gt; — &lt;em&gt;link, visited, hover, active&lt;/em&gt;. Si inviertes &lt;code&gt;:hover&lt;/code&gt; y &lt;code&gt;:link&lt;/code&gt;, el &lt;code&gt;:hover&lt;/code&gt; nunca se aplicaría.&lt;/p&gt;
&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem 1.25rem;background:#fff;color:#111;margin:1rem 0;"&gt;
 &lt;style&gt;
 .csfund-links a { font-family:Helvetica,Arial,sans-serif;font-weight:bold;text-decoration:none;color:#2a7ae2; }
 .csfund-links a:hover { text-decoration:underline;color:#c0392b; }
 &lt;/style&gt;
 &lt;p class="csfund-links" style="margin:0;"&gt;&lt;a href="#fundamentos-cascada-especificidad-herencia"&gt;Pasa el cursor sobre este enlace&lt;/a&gt; para ver el efecto del orden del código.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id="herencia-propiedades-que-viajan-hacia-abajo"&gt;Herencia: propiedades que viajan hacia abajo&lt;/h2&gt;
&lt;p&gt;La &lt;strong&gt;herencia&lt;/strong&gt; permite que ciertas propiedades de un elemento padre se transmitan a sus hijos. No todas las propiedades heredan: lo hacen principalmente las relacionadas con texto (&lt;code&gt;color&lt;/code&gt;, &lt;code&gt;font-family&lt;/code&gt;, &lt;code&gt;line-height&lt;/code&gt;, &lt;code&gt;text-align&lt;/code&gt;), mientras que las de caja (&lt;code&gt;margin&lt;/code&gt;, &lt;code&gt;padding&lt;/code&gt;, &lt;code&gt;border&lt;/code&gt;) no.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;tarjeta&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#1a5276&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;font-family&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Georgia&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;serif&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;div&lt;/span&gt; &lt;span style="color:#e06c75"&gt;class&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;tarjeta&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#e06c75"&gt;h4&lt;/span&gt;&amp;gt;Título heredado&amp;lt;/&lt;span style="color:#e06c75"&gt;h4&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;&lt;span style="color:#e06c75"&gt;p&lt;/span&gt;&amp;gt;Este párrafo hereda &amp;lt;&lt;span style="color:#e06c75"&gt;em&lt;/span&gt;&amp;gt;color&amp;lt;/&lt;span style="color:#e06c75"&gt;em&lt;/span&gt;&amp;gt; y &amp;lt;&lt;span style="color:#e06c75"&gt;em&lt;/span&gt;&amp;gt;font-family&amp;lt;/&lt;span style="color:#e06c75"&gt;em&lt;/span&gt;&amp;gt; del contenedor.&amp;lt;/&lt;span style="color:#e06c75"&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#e06c75"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem 1.25rem;background:#fff;margin:1rem 0;"&gt;
 &lt;div style="color:#1a5276;font-family:Georgia,serif;"&gt;
 &lt;h4 style="margin:.2rem 0;"&gt;Título heredado&lt;/h4&gt;
 &lt;p style="margin:.2rem 0;"&gt;Este párrafo hereda &lt;em&gt;color&lt;/em&gt; y &lt;em&gt;font-family&lt;/em&gt; del contenedor.&lt;/p&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="valores-especiales-inherit-e-initial"&gt;Valores especiales: &lt;code&gt;inherit&lt;/code&gt; e &lt;code&gt;initial&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Dos palabras clave te dan control explícito sobre la herencia:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;inherit&lt;/code&gt; — fuerza a una propiedad a tomar el valor del padre, incluso en propiedades que normalmente no heredan.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;initial&lt;/code&gt; — restablece la propiedad a su valor inicial según la especificación, ignorando la herencia.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="unidades-absolutas-vs-relativas"&gt;Unidades absolutas vs. relativas&lt;/h2&gt;
&lt;p&gt;El píxel (&lt;code&gt;px&lt;/code&gt;) es la unidad &lt;strong&gt;absoluta&lt;/strong&gt; más común. Existen otras (&lt;code&gt;pt&lt;/code&gt;, &lt;code&gt;cm&lt;/code&gt;, &lt;code&gt;in&lt;/code&gt;) con equivalencias fijas: &lt;code&gt;1in = 96px = 72pt&lt;/code&gt;. Sin embargo, las unidades &lt;strong&gt;relativas&lt;/strong&gt; son las que permiten construir interfaces que escalan con el contexto.&lt;/p&gt;
&lt;h3 id="em-relativo-al-elemento"&gt;&lt;code&gt;em&lt;/code&gt;: relativo al elemento&lt;/h3&gt;
&lt;p&gt;Un &lt;code&gt;em&lt;/code&gt; equivale al &lt;code&gt;font-size&lt;/code&gt; del propio elemento. Es ideal para &lt;code&gt;padding&lt;/code&gt;, &lt;code&gt;margin&lt;/code&gt; y &lt;code&gt;border-radius&lt;/code&gt;, porque estos escalan junto con el tamaño de fuente.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;caja&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;padding&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;border-radius&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; &lt;span style="color:#c678dd"&gt;background&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#ecf0f1&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;caja--pequena&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-size&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;12&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;caja--grande&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-size&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;20&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem 1.25rem;background:#fff;color:#111;margin:1rem 0;display:flex;gap:1rem;align-items:flex-start;flex-wrap:wrap;"&gt;
 &lt;span style="font-size:12px;padding:1em;border-radius:1em;background:#ecf0f1;color:#111;"&gt;padding 1em · 12px&lt;/span&gt;
 &lt;span style="font-size:20px;padding:1em;border-radius:1em;background:#ecf0f1;color:#111;"&gt;padding 1em · 20px&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;El &lt;code&gt;padding&lt;/code&gt; de ambas cajas es &lt;code&gt;1em&lt;/code&gt;, pero al cambiar el &lt;code&gt;font-size&lt;/code&gt; el espaciado escala proporcionalmente sin tocar la propiedad &lt;code&gt;padding&lt;/code&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Para convertir un tamaño en píxeles a &lt;code&gt;em&lt;/code&gt;, divide el tamaño deseado entre el tamaño heredado: si quieres &lt;code&gt;16px&lt;/code&gt; y el padre tiene &lt;code&gt;12px&lt;/code&gt;, entonces &lt;code&gt;16 / 12 = 1.333em&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id="rem-relativo-a-la-raíz"&gt;&lt;code&gt;rem&lt;/code&gt;: relativo a la raíz&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;rem&lt;/code&gt; (&lt;em&gt;root em&lt;/em&gt;) siempre toma como referencia el &lt;code&gt;font-size&lt;/code&gt; del elemento raíz (&lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; o &lt;code&gt;:root&lt;/code&gt;). Esto te da un punto de control global: cambiar el tamaño de la raíz redimensiona todo el documento de forma coherente.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:&lt;span style="color:#61afef"&gt;root&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-size&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;0.875&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;media&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;min-width&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;800px&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt; { :&lt;span style="color:#61afef"&gt;root&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-size&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; } }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@&lt;span style="color:#c678dd"&gt;media&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;&lt;span style="color:#e06c75"&gt;min-width&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#e06c75"&gt;1200px&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt; { :&lt;span style="color:#61afef"&gt;root&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-size&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1.125&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;; } }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Una práctica habitual: usar &lt;code&gt;rem&lt;/code&gt; para tipografía, &lt;code&gt;px&lt;/code&gt; para bordes y &lt;code&gt;em&lt;/code&gt; para &lt;code&gt;padding&lt;/code&gt;, &lt;code&gt;margin&lt;/code&gt; y &lt;code&gt;border-radius&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="unidades-relativas-al-viewport"&gt;Unidades relativas al viewport&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;vw&lt;/code&gt; — 1% del ancho del viewport.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vh&lt;/code&gt; — 1% del alto del viewport.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vmin&lt;/code&gt; — 1% de la dimensión más pequeña entre ancho y alto.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vmax&lt;/code&gt; — 1% de la dimensión más grande.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="calc-para-combinar-unidades"&gt;&lt;code&gt;calc()&lt;/code&gt; para combinar unidades&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;calc()&lt;/code&gt; permite operar entre unidades de distinta naturaleza, algo imposible de otra forma. Es muy útil para tipografía fluida:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:&lt;span style="color:#61afef"&gt;root&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;font-size&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;calc&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;0.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;vw&lt;/span&gt;); }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="números-sin-unidad-y-line-height"&gt;Números sin unidad y &lt;code&gt;line-height&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Si declaras un número sin unidad en &lt;code&gt;line-height&lt;/code&gt;, este actúa como un &lt;strong&gt;factor multiplicador&lt;/strong&gt; del &lt;code&gt;font-size&lt;/code&gt; del elemento. Es la forma recomendada, porque cada descendiente calcula su propia altura de línea a partir de su tamaño de fuente.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;body&lt;/span&gt; { &lt;span style="color:#c678dd"&gt;line-height&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1.5&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="custom-properties-variables-css"&gt;Custom properties (variables CSS)&lt;/h2&gt;
&lt;p&gt;Las &lt;strong&gt;variables CSS&lt;/strong&gt; se declaran con el prefijo &lt;code&gt;--&lt;/code&gt; y se consumen con la función &lt;code&gt;var()&lt;/code&gt;. A diferencia de las variables de un preprocesador, son dinámicas: viven en el DOM y respetan la cascada y la herencia.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:&lt;span style="color:#61afef"&gt;root&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;--color-marca&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#2a9da9&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;--color-texto&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#1c2833&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;panel&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#61afef;font-weight:bold"&gt;var&lt;/span&gt;(&lt;span style="color:#56b6c2"&gt;--&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;color&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;-&lt;/span&gt;&lt;span style="color:#e06c75"&gt;texto&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;border-left&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;4&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;px&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;solid&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;var&lt;/span&gt;(&lt;span style="color:#56b6c2"&gt;--&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;color&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;-&lt;/span&gt;&lt;span style="color:#e06c75"&gt;marca&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;var()&lt;/code&gt; acepta un segundo argumento como valor de respaldo: &lt;code&gt;var(--color-secundario, #888)&lt;/code&gt; usará &lt;code&gt;#888&lt;/code&gt; si la variable no está definida.&lt;/p&gt;
&lt;h3 id="redefinir-variables-por-contexto"&gt;Redefinir variables por contexto&lt;/h3&gt;
&lt;p&gt;Como las variables respetan la cascada, puedes sobrescribirlas dentro de un bloque para crear temas locales. Aquí el mismo componente &lt;code&gt;.panel&lt;/code&gt; se reconfigura dentro de &lt;code&gt;.tema-oscuro&lt;/code&gt; cambiando solo las variables:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:&lt;span style="color:#61afef"&gt;root&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;--fondo&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#fff&lt;/span&gt;; &lt;span style="color:#e06c75"&gt;--texto&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#111&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;tema-oscuro&lt;/span&gt; { &lt;span style="color:#e06c75"&gt;--fondo&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#2c3e50&lt;/span&gt;; &lt;span style="color:#e06c75"&gt;--texto&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;#ecf0f1&lt;/span&gt;; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.&lt;span style="color:#e5c07b"&gt;panel&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;background&lt;/span&gt;: &lt;span style="color:#61afef;font-weight:bold"&gt;var&lt;/span&gt;(&lt;span style="color:#56b6c2"&gt;--&lt;/span&gt;&lt;span style="color:#e06c75"&gt;fondo&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;color&lt;/span&gt;: &lt;span style="color:#61afef;font-weight:bold"&gt;var&lt;/span&gt;(&lt;span style="color:#56b6c2"&gt;--&lt;/span&gt;&lt;span style="color:#e06c75"&gt;texto&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;padding&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;border-radius&lt;/span&gt;: &lt;span style="color:#d19a66"&gt;.5&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="border:1px solid #d0d0d0;border-radius:.5rem;padding:1rem;background:#fff;margin:1rem 0;display:flex;gap:1rem;flex-wrap:wrap;"&gt;
 &lt;div style="background:#fff;color:#111;padding:1em;border-radius:.5em;border:1px solid #ddd;flex:1;min-width:180px;"&gt;
 &lt;strong&gt;Panel claro&lt;/strong&gt;
 &lt;p style="margin:.4rem 0 0;"&gt;Usa las variables por defecto de &lt;code&gt;:root&lt;/code&gt;.&lt;/p&gt;
 &lt;/div&gt;
 &lt;div style="background:#2c3e50;color:#ecf0f1;padding:1em;border-radius:.5em;flex:1;min-width:180px;"&gt;
 &lt;strong&gt;Panel oscuro&lt;/strong&gt;
 &lt;p style="margin:.4rem 0 0;"&gt;Las mismas reglas, con las variables redefinidas.&lt;/p&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;El componente no cambió ni una línea: solo redefinimos las variables en un contenedor superior. Ese es el poder de combinar herencia y &lt;em&gt;custom properties&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;La cascada, la especificidad y la herencia forman el núcleo conceptual de CSS. Dominarlos te permite predecir qué regla gana sin recurrir a parches. Sumado a un buen uso de unidades relativas y variables, tienes la base para escribir estilos escalables y mantenibles.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 Próximo en la serie: los &lt;strong&gt;selectores&lt;/strong&gt; de CSS, la herramienta con la que apuntamos con precisión a los elementos que queremos estilizar.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>Agentes Especializados: Colaboración Multi-Agente y Nuevas Fronteras</title><link>https://blog.dacadev.com/generative-ai/agents/agentes-especializados-multi-agente/</link><pubDate>Thu, 21 May 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/generative-ai/agents/agentes-especializados-multi-agente/</guid><dc:creator>Dacadev</dc:creator><category>IA generativa</category><description>Descubre las fronteras de la IA con agentes especializados. Aprende sobre colaboración multi-agente, agentes multimodales, coding agents y agentes ultra-eficientes (Tiny Agents).</description><media:content url="https://blog.dacadev.com/images/generative-ai/agents/03-agentes-especializados/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#el-universo-de-los-agentes-especializados"&gt;El Universo de los Agentes Especializados&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#colaboración-multi-agente-agente-único-vs-multi-agente"&gt;Colaboración Multi-Agente: Agente Único vs. Multi-Agente&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#la-arquitectura-del-agente-supervisor-supervisor-agent"&gt;La Arquitectura del Agente Supervisor (Supervisor Agent)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#el-agente-multimodal"&gt;El Agente Multimodal&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#el-coding-agent-agente-de-programación"&gt;El Coding Agent (Agente de Programación)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#tiny-agents-resolviendo-la-eficiencia-y-los-costos"&gt;Tiny Agents: Resolviendo la Eficiencia y los Costos&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#1-creación-de-modelos-más-pequeños-distillation"&gt;1. Creación de Modelos más Pequeños (Distillation)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#2-arquitecturas-de-llm-más-eficientes-moe-y-ssm"&gt;2. Arquitecturas de LLM más Eficientes (MoE y SSM)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#3-disminución-del-costo-de-inferencia-speculative-decoding"&gt;3. Disminución del Costo de Inferencia (Speculative Decoding)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#4-modelos-con-mayor-performance-en-razonamiento-hierarchical-decoding"&gt;4. Modelos con Mayor Performance en Razonamiento (Hierarchical Decoding)&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Cuando un solo agente de &lt;strong&gt;Inteligencia Artificial&lt;/strong&gt; intenta hacerlo todo —desde buscar en internet y escribir código hasta redactar correos o gestionar la base de datos—, suele toparse con un cuello de botella. Al igual que en un equipo de desarrollo de software no le pedirías a un diseñador UX que configure el cluster de Kubernetes, en la &lt;strong&gt;Inteligencia Artificial&lt;/strong&gt; el futuro pertenece a los &lt;strong&gt;Agentes Especializados&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;¿Cómo logramos que múltiples agentes colaboren entre sí de forma armoniosa?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;¿Qué nuevas capacidades traen los agentes multimodales y de programación?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;¿Y cómo resolvemos el gran problema del costo y consumo de tokens de estos sistemas?&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;En este artículo profundizaremos enlos agentes especializados. Exploraremos la arquitectura de colaboración &lt;strong&gt;Multi-Agente&lt;/strong&gt;, descubriremos el potencial de los &lt;strong&gt;Agentes Multimodales&lt;/strong&gt; y &lt;strong&gt;Coding Agents&lt;/strong&gt;, y analizaremos las estrategias para construir &lt;strong&gt;Tiny Agents&lt;/strong&gt; sumamente eficientes. 🚀&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;hr&gt;
&lt;h2 id="el-universo-de-los-agentes-especializados"&gt;El Universo de los Agentes Especializados&lt;/h2&gt;
&lt;p&gt;A medida que las necesidades de automatización se vuelven más complejas, los desarrolladores de IA hemos aprendido a fragmentar los problemas en lugar de crear un único agente monolítico. Esto nos lleva a cuatro categorías principales de especialización:&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 %% Categorías de Agentes Especializados
 Root[🧬 Agentes Especializados]

 Root --&amp;gt; MAC[🤝 Colaboración Multi-Agente]
 Root --&amp;gt; MM[👁️ Agentes Multimodales]
 Root --&amp;gt; CA[💻 Coding Agents]
 Root --&amp;gt; TA[&amp;#34;⚡ Tiny Agents (Eficiencia)&amp;#34;]

 MAC --&amp;gt; MAC_Desc[&amp;#34;Agentes que dividen tareas y colaboran entre sí&amp;#34;]
 MM --&amp;gt; MM_Desc[&amp;#34;Comprenden y generan texto, audio, imagen y video&amp;#34;]
 CA --&amp;gt; CA_Desc[&amp;#34;Escriben, ejecutan y auto-depuran código&amp;#34;]
 TA --&amp;gt; TA_Desc[&amp;#34;Modelos compactos optimizados para bajo costo e inferencia rápida&amp;#34;]
&lt;/pre&gt;

&lt;hr&gt;
&lt;h2 id="colaboración-multi-agente-agente-único-vs-multi-agente"&gt;Colaboración Multi-Agente: Agente Único vs. Multi-Agente&lt;/h2&gt;
&lt;p&gt;En un sistema de &lt;strong&gt;Agente Único (Single Agent)&lt;/strong&gt;, un solo LLM generalista se encarga de procesar la consulta, gestionar la memoria, seleccionar las herramientas y generar el plan final. Aunque es un diseño sencillo y efectivo para tareas contenidas, genera una enorme presión sobre la ventana de contexto del modelo y aumenta drásticamente el riesgo de alucinaciones a medida que sumamos más herramientas al arsenal.&lt;/p&gt;
&lt;p&gt;Por el contrario, un &lt;strong&gt;Sistema Multi-Agente (Multi-Agent System)&lt;/strong&gt; divide las responsabilidades entre varios agentes especializados que interactúan entre sí. Cada agente cuenta con un rol definido, una memoria local ajustada a su función y un conjunto limitado de herramientas específicas. Esto reduce el ruido, optimiza el tamaño de los prompts y permite estructurar flujos de trabajo altamente modulares.&lt;/p&gt;
&lt;p&gt;Comparemos estas dos aproximaciones de manera visual:&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 subgraph Multi[&amp;#34;Sistema Multi-Agente (Multi-Agent)&amp;#34;]
 direction TB
 Q2[👤 Consulta] --&amp;gt; Supervisor[👑 Agente Supervisor]
 Supervisor &amp;lt;--&amp;gt; AgentA[💻 Agente de Código]
 Supervisor &amp;lt;--&amp;gt; AgentB[💬 Agente de Mensajería]
 Supervisor &amp;lt;--&amp;gt; AgentC[🔍 Agente de Búsqueda]
 AgentA &amp;amp; AgentB &amp;amp; AgentC --&amp;gt; Ans2[🎯 Respuesta]
 end

 subgraph Single[&amp;#34;Un Solo Agente (Single Agent)&amp;#34;]
 direction TB
 Q1[👤 Consulta] --&amp;gt; SA[🧠 Agente Generalista]
 subgraph SABrain[&amp;#34;Cerebro Complejo&amp;#34;]
 direction LR
 LLM1[Reasoning LLM] --- Mem1[(Memoria)]
 LLM1 --- Tools1[🔧 Herramientas]
 LLM1 --- Plan1[📋 Planificación]
 end
 SA --&amp;gt; Ans1[🎯 Respuesta]
 end
&lt;/pre&gt;

&lt;hr&gt;
&lt;h2 id="la-arquitectura-del-agente-supervisor-supervisor-agent"&gt;La Arquitectura del Agente Supervisor (Supervisor Agent)&lt;/h2&gt;
&lt;p&gt;Uno de los patrones de diseño más exitosos en sistemas multi-agente es el de &lt;strong&gt;Agente Supervisor (Supervisor Agent)&lt;/strong&gt;. En este patrón, el supervisor actúa como el &amp;ldquo;director de orquesta&amp;rdquo; o el gestor principal del equipo de desarrollo.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;El &lt;strong&gt;Supervisor&lt;/strong&gt; recibe la consulta compleja del usuario.&lt;/li&gt;
&lt;li&gt;Analiza qué sub-tareas se necesitan resolver para cumplir la meta y descompone el problema general.&lt;/li&gt;
&lt;li&gt;Asigna cada sub-tarea al agente especialista correspondiente (el Agente de Código, de Búsqueda o de Mensajería), tratándolos prácticamente como si fueran &amp;ldquo;herramientas avanzadas&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Los agentes especialistas procesan las sub-tareas utilizando sus &lt;strong&gt;herramientas específicas&lt;/strong&gt; y devuelven el resultado al supervisor.&lt;/li&gt;
&lt;li&gt;El supervisor consolida las respuestas parciales y, si es necesario, replanifica el flujo antes de entregar la respuesta definitiva al usuario.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;En este modelo, el &lt;strong&gt;Agente Supervisor&lt;/strong&gt; suele estar respaldado por el LLM más potente debido a la complejidad que requiere la planificación y asignación de tareas, mientras que los especialistas pueden funcionar perfectamente con modelos más rápidos y económicos.&lt;/p&gt;
&lt;p&gt;Observemos esta sofisticada estructura jerárquica en acción:&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 Query[👤 Consulta / Query] --&amp;gt; Sup[👑 Agente Supervisor]

 subgraph SupTools[&amp;#34;Agentes como Herramientas (Supervisor)&amp;#34;]
 Sup --- ToolC[💻 Coding Tool]
 Sup --- ToolM[💬 Messaging Tool]
 Sup --- ToolS[🔍 Search Tool]
 end

 Sup &amp;lt;--&amp;gt; CA[💻 Coding Agent]
 Sup &amp;lt;--&amp;gt; MA[💬 Messaging Agent]
 Sup &amp;lt;--&amp;gt; SA[🔍 Search Agent]

 subgraph CATools[&amp;#34;Herramientas del Agente de Código&amp;#34;]
 CA --- T_Py[🐍 python]
 CA --- T_VS[💻 vscode]
 CA --- T_GH[🐙 github]
 end

 subgraph MATools[&amp;#34;Herramientas de Mensajería&amp;#34;]
 MA --- T_Sl[💬 slack]
 MA --- T_Ds[👾 discord]
 end

 subgraph SATools[&amp;#34;Herramientas de Búsqueda&amp;#34;]
 SA --- T_Go[🔍 google]
 SA --- T_Ar[📄 ArXiv]
 SA --- T_Wi[🌐 Wikipedia]
 end
&lt;/pre&gt;

&lt;hr&gt;
&lt;h2 id="el-agente-multimodal"&gt;El Agente Multimodal&lt;/h2&gt;
&lt;p&gt;El mundo real y la web digital no se componen únicamente de texto plano. Para interactuar plenamente con nuestro entorno, necesitamos agentes capaces de operar en múltiples formatos de datos. Aquí es donde los &lt;strong&gt;Agentes Multimodales&lt;/strong&gt; están ganando un enorme terreno.&lt;/p&gt;
&lt;p&gt;La capacidad de que un agente sea multimodal depende enteramente del LLM que actúe como su &amp;ldquo;cerebro&amp;rdquo;. Definimos a un agente como multimodal cuando su modelo subyacente es capaz de:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Comprender múltiples modalidades (Entrada/Input)&lt;/strong&gt;: El modelo procesa de forma nativa imágenes, archivos PDF estructurados, diagramas, flujos de audio o incluso video sin necesidad de convertirlos previamente a texto mediante software secundario OCR.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generar múltiples modalidades (Salida/Output)&lt;/strong&gt;: El agente puede responder dibujando diagramas, generando archivos de audio estructurados, creando código visual interactivo o interactuando directamente en interfaces visuales de usuario (mediante herramientas de &lt;em&gt;Computer Use&lt;/em&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="el-coding-agent-agente-de-programación"&gt;El Coding Agent (Agente de Programación)&lt;/h2&gt;
&lt;p&gt;Uno de los tipos de agentes especializados más populares es el &lt;strong&gt;Coding Agent&lt;/strong&gt;. A diferencia de los asistentes de chat tradicionales (que se limitan a dar sugerencias de código en una ventana de conversación estática), un Coding Agent opera de forma activa sobre entornos de desarrollo:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Lectura e investigación&lt;/strong&gt;: Lee el código fuente del repositorio y comprende la arquitectura general.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Planificación y desarrollo&lt;/strong&gt;: Escribe nuevas funciones, modifica archivos específicos y gestiona el flujo de control.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ejecución y pruebas&lt;/strong&gt;: Ejecuta compiladores y motores de pruebas unitarias locales para validar sus cambios.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto-depuración (Self-debugging)&lt;/strong&gt;: Si el compilador o las pruebas devuelven un error, el agente analiza el mensaje de salida, actualiza su plan, corrige su código y vuelve a ejecutar las pruebas hasta lograr que todo compile y funcione de forma exitosa.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="tiny-agents-resolviendo-la-eficiencia-y-los-costos"&gt;Tiny Agents: Resolviendo la Eficiencia y los Costos&lt;/h2&gt;
&lt;p&gt;Aunque los sistemas agénticos son sumamente potentes, tienen un gran inconveniente oculto: &lt;strong&gt;el costo&lt;/strong&gt;. Un agente autónomo puede tomar docenas de pasos secuenciales para resolver una tarea, consumiendo millones de tokens en el proceso sin que el desarrollador o usuario puedan anticipar la cantidad exacta de antemano.&lt;/p&gt;
&lt;p&gt;Para evitar que el uso y costo de agentes se salga de control, la comunidad científica de IA ha desarrollado los &lt;strong&gt;Tiny Agents&lt;/strong&gt;: agentes ultra-eficientes y veloces basados en modelos pequeños optimizados para tareas muy puntuales.&lt;/p&gt;
&lt;p&gt;Existen cuatro categorías clave donde podemos buscar optimizaciones para nuestros agentes:&lt;/p&gt;
&lt;h3 id="1-creación-de-modelos-más-pequeños-distillation"&gt;1. Creación de Modelos más Pequeños (Distillation)&lt;/h3&gt;
&lt;p&gt;Mediante técnicas de &lt;strong&gt;destilación de conocimiento (knowledge distillation)&lt;/strong&gt;, podemos entrenar un modelo pequeño (ej. de 1.5B o 3B parámetros) utilizando las respuestas detalladas y las trayectorias de razonamiento generadas por modelos gigantes (ej. de 405B parámetros). De esta manera, el modelo compacto conserva una alta tasa de acierto en tareas específicas pero a una fracción del costo y tamaño.&lt;/p&gt;
&lt;h3 id="2-arquitecturas-de-llm-más-eficientes-moe-y-ssm"&gt;2. Arquitecturas de LLM más Eficientes (MoE y SSM)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mixture of Experts (MoE)&lt;/strong&gt;: Modelos que solo activan una pequeña porción de sus redes neuronales (los &amp;ldquo;expertos&amp;rdquo;) para procesar un token específico, logrando una altísima velocidad de inferencia a bajo costo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;State Space Models (SSM)&lt;/strong&gt;: Arquitecturas alternativas a los &lt;em&gt;Transformers&lt;/em&gt; tradicionales (como &lt;em&gt;Mamba&lt;/em&gt;) que eliminan el crecimiento cuadrático del costo computacional de la atención en textos extremadamente largos, ideales para procesar enormes repositorios o históricos de conversación.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-disminución-del-costo-de-inferencia-speculative-decoding"&gt;3. Disminución del Costo de Inferencia (Speculative Decoding)&lt;/h3&gt;
&lt;p&gt;La &lt;strong&gt;decodificación especulativa (speculative decoding)&lt;/strong&gt; utiliza un modelo &amp;ldquo;asistente&amp;rdquo; sumamente pequeño y rápido para predecir (borrador) secuencialmente varios tokens de respuesta de manera rápida. Luego, el LLM principal (más grande y preciso) evalúa y valida estos tokens especulados en un solo paso paralelo, acelerando drásticamente el tiempo de generación final.&lt;/p&gt;
&lt;h3 id="4-modelos-con-mayor-performance-en-razonamiento-hierarchical-decoding"&gt;4. Modelos con Mayor Performance en Razonamiento (Hierarchical Decoding)&lt;/h3&gt;
&lt;p&gt;Consiste en implementar patrones lógicos jerárquicos y recursivos donde el agente descompone internamente el problema de forma recursiva antes de generar texto, evitando la generación redundante de tokens innecesarios y optimizando cada paso de inferencia al máximo.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;El camino de los sistemas monolíticos hacia las redes de &lt;strong&gt;Agentes Especializados&lt;/strong&gt; es una evolución natural y sumamente emocionante. Al combinar la orquestación modular de &lt;strong&gt;sistemas multi-agente&lt;/strong&gt;, la flexibilidad de las capacidades &lt;strong&gt;multimodales&lt;/strong&gt; y las optimizaciones de costo de los &lt;strong&gt;Tiny Agents&lt;/strong&gt;, podemos diseñar soluciones de Inteligencia Artificial que no solo parezcan sacadas de la ciencia ficción, sino que sean escalables, rentables y robustas en el mundo real.&lt;/p&gt;
&lt;p&gt;¡Con este artículo cerramos nuestra trilogía introductoria sobre la teoría y arquitectura de agentes de Inteligencia Artificial! En los próximos tutoriales prácticos empezaremos a picar código y a construir nuestros propios agentes colaborativos. ¡Manos a la obra!&lt;/p&gt;</content:encoded></item><item><title>Tablas Hash, Pilas y Colas: Estructuras de Datos de Alto Rendimiento</title><link>https://blog.dacadev.com/programacion/estructura-datos-y-algoritmos/03-hash-tables-stacks-y-queues/</link><pubDate>Tue, 19 May 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/estructura-datos-y-algoritmos/03-hash-tables-stacks-y-queues/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Aprende el funcionamiento interno de las Tablas Hash, Hashing y Colisiones. Guía práctica y visual de Stacks (Pilas) y Queues (Colas) en TypeScript.</description><media:content url="https://blog.dacadev.com/images/programming/structures-algorithms/03-hash-tables-stacks-queues/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#1-qué-es-una-tabla-hash-hash-table"&gt;1. ¿Qué es una Tabla Hash (Hash Table)?&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#cómo-funciona-el-hashing"&gt;¿Cómo funciona el Hashing?&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#colisiones-y-load-factor"&gt;Colisiones y Load Factor&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#eficiencia-de-las-operaciones-en-una-hash-table"&gt;Eficiencia de las Operaciones en una Hash Table&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#ejemplo-práctico-optimizando-código-con-tablas-hash"&gt;Ejemplo Práctico: Optimizando código con Tablas Hash&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#la-versión-lenta-on-cdot-m---bucles-anidados"&gt;La versión lenta (O(N \cdot M)) - Bucles anidados:&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#la-versión-veloz-on--m---usando-una-tabla-hash"&gt;La versión veloz (O(N + M)) - Usando una Tabla Hash:&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#pilas-stacks"&gt;Pilas (Stacks)&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#sus-3-reglas-de-oro"&gt;Sus 3 Reglas de Oro:&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#colas-queues"&gt;Colas (Queues)&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#sus-3-reglas-de-oro-1"&gt;Sus 3 Reglas de Oro:&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Hasta ahora hemos visto estructuras secuenciales como los Arrays, donde buscar un elemento requiere revisar celda por celda &lt;em&gt;O(N)&lt;/em&gt; o usar búsqueda binaria &lt;em&gt;O(log N)&lt;/em&gt; si están ordenados. Pero, ¿qué pasaría si te dijera que existe una estructura capaz de buscar, insertar y borrar datos en &lt;strong&gt;un solo paso &lt;em&gt;O(1)&lt;/em&gt;&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;Hoy explicaremos las &lt;strong&gt;Tablas Hash (Hash Tables)&lt;/strong&gt;,las &lt;strong&gt;Pilas (Stacks)&lt;/strong&gt; y las &lt;strong&gt;Colas (Queues)&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-qué-es-una-tabla-hash-hash-table"&gt;1. ¿Qué es una Tabla Hash (Hash Table)?&lt;/h2&gt;
&lt;p&gt;Una &lt;strong&gt;Tabla Hash&lt;/strong&gt; (conocida en Python como &lt;em&gt;diccionario&lt;/em&gt;, en JavaScript como &lt;em&gt;objeto&lt;/em&gt; o &lt;em&gt;Map&lt;/em&gt;, y en Go como &lt;em&gt;map&lt;/em&gt;) es una estructura que asocia &lt;strong&gt;claves (keys)&lt;/strong&gt; con &lt;strong&gt;valores (values)&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A diferencia de los Arrays, donde los elementos están ordenados por índices numéricos continuos, las Tablas Hash son estructuras no ordenadas. Su velocidad absurda radica en su proceso interno: el &lt;strong&gt;Hashing&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="cómo-funciona-el-hashing"&gt;¿Cómo funciona el Hashing?&lt;/h3&gt;
&lt;p&gt;Cuando guardamos un dato en una Tabla Hash (por ejemplo, &lt;code&gt;{&amp;quot;cab&amp;quot; =&amp;gt; &amp;quot;taxi&amp;quot;}&lt;/code&gt;), la computadora no busca una celda libre al azar. Utiliza una &lt;strong&gt;función hash (hash function)&lt;/strong&gt; para convertir la clave de texto en un índice numérico específico.&lt;/p&gt;
&lt;p&gt;Supongamos que inventamos una función hash súper simple que suma el valor alfabético de las letras de la clave:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;A = 1, B = 2, C = 3, D = 4, E = 5&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Si guardamos la clave &lt;code&gt;&amp;quot;ACE&amp;quot;&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;A(1) + C(3) + E(5) = 9&lt;/em&gt;. El valor se almacena en el índice &lt;strong&gt;9&lt;/strong&gt; de nuestra memoria física.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Si guardamos &lt;code&gt;&amp;quot;CAB&amp;quot;&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;C(3) + A(1) + B(2) = 6&lt;/em&gt;. El valor se almacena en el índice &lt;strong&gt;6&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 Key[&amp;#34;Clave: &amp;#39;ACE&amp;#39;&amp;#34;] --&amp;gt; HashFunc[&amp;#34;Función Hash&amp;lt;br/&amp;gt;(Suma de letras)&amp;#34;]
 HashFunc --&amp;gt; Index[&amp;#34;Índice: 9&amp;#34;]
 Index --&amp;gt; Memory[&amp;#34;[Celda 9] = &amp;#39;star&amp;#39;&amp;#34;]
&lt;/pre&gt;

&lt;p&gt;Cuando quieres buscar el valor asociado a &lt;code&gt;&amp;quot;ACE&amp;quot;&lt;/code&gt;, la computadora no recorre toda la tabla. Simplemente calcula de nuevo &lt;code&gt;Hash(&amp;quot;ACE&amp;quot;) = 9&lt;/code&gt; y accede de forma instantánea al índice 9 en &lt;strong&gt;1 paso (O(1))&lt;/strong&gt;. ¡Es brillante!&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="colisiones-y-load-factor"&gt;Colisiones y Load Factor&lt;/h2&gt;
&lt;p&gt;¿Qué pasa si intentamos insertar &lt;code&gt;&amp;quot;DAB&amp;quot;&lt;/code&gt; en nuestro ejemplo anterior?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;D(4) + A(1) + B(2) = 7&lt;/em&gt;
¿Y si intentamos insertar &lt;code&gt;&amp;quot;BAD&amp;quot;&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;&lt;em&gt;B(2) + A(1) + D(4) = 7&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ambas claves dan el mismo índice, a esto se le conoce como &lt;strong&gt;Colisión Hash&lt;/strong&gt;. Cuando esto ocurre, la celda 7 debe almacenar una sub-lista de valores, lo que degrada el rendimiento de la búsqueda.&lt;/p&gt;
&lt;p&gt;Para evitar colisiones en la vida real, las funciones hash usan matemáticas complejas y se rigen por la regla del &lt;strong&gt;Factor de Carga (Load Factor)&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La proporción ideal es tener &lt;strong&gt;10 celdas de memoria por cada 7 elementos&lt;/strong&gt; almacenados (un factor de carga de 0.7). Esto mantiene un equilibrio perfecto entre uso de memoria y prevención de colisiones.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="eficiencia-de-las-operaciones-en-una-hash-table"&gt;Eficiencia de las Operaciones en una Hash Table&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Operación&lt;/th&gt;
 &lt;th&gt;Por Clave (Key)&lt;/th&gt;
 &lt;th&gt;Por Valor (Value)&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Búsqueda&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;O(1)&lt;/strong&gt; (Constante)&lt;/td&gt;
 &lt;td&gt;O(N) (Lineal)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Inserción&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;O(1)&lt;/strong&gt; (Constante)&lt;/td&gt;
 &lt;td&gt;-&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Eliminación&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;O(1)&lt;/strong&gt; (Constante)&lt;/td&gt;
 &lt;td&gt;-&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;La búsqueda de &lt;em&gt;O(1)&lt;/em&gt; solo funciona en &lt;strong&gt;una dirección&lt;/strong&gt;: desde la clave al valor. Si necesitas buscar una clave a partir de su valor, la computadora obligatoriamente deberá recorrer toda la estructura de forma lineal (O(N)).&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;hr&gt;
&lt;h2 id="ejemplo-práctico-optimizando-código-con-tablas-hash"&gt;Ejemplo Práctico: Optimizando código con Tablas Hash&lt;/h2&gt;
&lt;p&gt;Imagina que debes escribir una función en TypeScript que determine si un arreglo es un subconjunto de otro (es decir, si todos los elementos de un arreglo &lt;code&gt;array2&lt;/code&gt; existen en &lt;code&gt;array1&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id="la-versión-lenta-on-cdot-m---bucles-anidados"&gt;La versión lenta (O(N \cdot M)) - Bucles anidados:&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;isSubsetSlow&lt;/span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;T&lt;/span&gt;&amp;gt;(&lt;span style="color:#e06c75"&gt;arr1&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;T&lt;/span&gt;[], &lt;span style="color:#e06c75"&gt;arr2&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;T&lt;/span&gt;[])&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;boolean&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;// Compara cada elemento del segundo arreglo contra todos los del primero
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; (&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;val2&lt;/span&gt; &lt;span style="color:#c678dd"&gt;of&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr2&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;found&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;boolean&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; (&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;val1&lt;/span&gt; &lt;span style="color:#c678dd"&gt;of&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;val2&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;===&lt;/span&gt; &lt;span style="color:#e06c75"&gt;val1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;found&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; (&lt;span style="color:#56b6c2"&gt;!&lt;/span&gt;&lt;span style="color:#e06c75"&gt;found&lt;/span&gt;) &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="la-versión-veloz-on--m---usando-una-tabla-hash"&gt;La versión veloz (O(N + M)) - Usando una Tabla Hash:&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;isSubsetFast&lt;/span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;T&lt;/span&gt; &lt;span style="color:#e06c75"&gt;extends&lt;/span&gt; &lt;span style="color:#e06c75"&gt;PropertyKey&lt;/span&gt;&amp;gt;(&lt;span style="color:#e06c75"&gt;arr1&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;T&lt;/span&gt;[], &lt;span style="color:#e06c75"&gt;arr2&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;T&lt;/span&gt;[])&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;boolean&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;hashTable&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;Record&lt;/span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;T&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;boolean&lt;/span&gt;&amp;gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {} &lt;span style="color:#c678dd"&gt;as&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Record&lt;/span&gt;&amp;lt;&lt;span style="color:#e06c75"&gt;T&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;boolean&lt;/span&gt;&amp;gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;// Guardamos todos los elementos de arr1 en la tabla hash en O(N)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; (&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;value&lt;/span&gt; &lt;span style="color:#c678dd"&gt;of&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;hashTable&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;value&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;// Comprobamos la existencia de arr2 en O(M)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; (&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;value&lt;/span&gt; &lt;span style="color:#c678dd"&gt;of&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr2&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; (&lt;span style="color:#56b6c2"&gt;!&lt;/span&gt;&lt;span style="color:#e06c75"&gt;hashTable&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;value&lt;/span&gt;]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Al transformar la búsqueda lineal anidada en una búsqueda instantánea en una Tabla Hash, convertimos un algoritmo pesado de complejidad multiplicativa a uno de complejidad sumatoria. ¡Es la diferencia entre que un proceso tarde horas o milisegundos!&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="pilas-stacks"&gt;Pilas (Stacks)&lt;/h2&gt;
&lt;p&gt;Las &lt;strong&gt;Pilas (Stacks)&lt;/strong&gt; son una estructura de datos abstracta y altamente restrictiva. A diferencia de un Array normal donde puedes leer o insertar en cualquier parte, en un Stack las reglas son estrictas.&lt;/p&gt;
&lt;p&gt;Se rigen bajo el principio &lt;strong&gt;LIFO (Last In, First Out)&lt;/strong&gt;: el último elemento en entrar es el primero en salir. Imagínalo como una pila de platos en un restaurante, solo puedes interactuar con el plato de arriba.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 subgraph Pila Stack - LIFO
 direction TB
 E3[&amp;#34;[Plato 3] &amp;lt;-- Cima (Peek/Pop)&amp;#34;]
 E2[&amp;#34;[Plato 2]&amp;#34;]
 E1[&amp;#34;[Plato 1] &amp;lt;-- Base&amp;#34;]
 end
&lt;/pre&gt;

&lt;h3 id="sus-3-reglas-de-oro"&gt;Sus 3 Reglas de Oro:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Los datos solo se pueden insertar al final (&lt;strong&gt;Push&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Los datos solo se pueden eliminar del final (&lt;strong&gt;Pop&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Solo se puede leer el último elemento (&lt;strong&gt;Peek&lt;/strong&gt; o Cima).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;¿Por qué usar una estructura tan restrictiva?&lt;/strong&gt;
Porque nos da seguridad. Al restringir las operaciones de acceso, garantizamos que nadie pueda corromper el orden de los datos intermedios. Es el motor detrás del botón &amp;ldquo;Deshacer&amp;rdquo; (Ctrl+Z) de tu editor de texto y del &lt;strong&gt;Call Stack&lt;/strong&gt; de tu procesador.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="colas-queues"&gt;Colas (Queues)&lt;/h2&gt;
&lt;p&gt;Las &lt;strong&gt;Colas (Queues)&lt;/strong&gt; son la contraparte directa del Stack. Representan fielmente la fila de un banco o supermercado.&lt;/p&gt;
&lt;p&gt;Se rigen por el principio &lt;strong&gt;FIFO (First In, First Out)&lt;/strong&gt;: el primer elemento en llegar es el primero en ser atendido.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 subgraph Cola Queue - FIFO
 direction LR
 S1[&amp;#34;[Cliente 1] En cabeza (Atender/Dequeue)&amp;#34;] --&amp;gt; S2[&amp;#34;[Cliente 2]&amp;#34;] --&amp;gt; S3[&amp;#34;[Cliente 3] En cola (Llegada/Enqueue)&amp;#34;]
 end
&lt;/pre&gt;

&lt;h3 id="sus-3-reglas-de-oro-1"&gt;Sus 3 Reglas de Oro:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Los datos solo se insertan al final (&lt;strong&gt;Enqueue&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Los datos solo se eliminan del inicio (&lt;strong&gt;Dequeue&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Solo se puede leer el elemento del inicio.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Casos de uso comunes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Colas de impresión: los documentos se imprimen exactamente en el orden en que fueron enviados.&lt;/li&gt;
&lt;li&gt;Gestión de tareas asíncronas en servidores web (Message Queues).&lt;/li&gt;
&lt;li&gt;Procesos de background en sistemas operativos.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Entendiendo la Notación Big O y los Algoritmos de Ordenamiento Básicos</title><link>https://blog.dacadev.com/programacion/estructura-datos-y-algoritmos/02-big-o-notation-y-algoritmos-de-ordenamiento/</link><pubDate>Mon, 18 May 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/estructura-datos-y-algoritmos/02-big-o-notation-y-algoritmos-de-ordenamiento/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Aprende a analizar la complejidad temporal de tu código con Big O. Explicación paso a paso de Bubble Sort, Selection Sort e Insertion Sort con ejemplos en Python.</description><media:content url="https://blog.dacadev.com/images/programming/structures-algorithms/02-big-o-and-sorting-algorithms/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#qué-es-la-notación-big-o"&gt;¿Qué es la Notación Big O?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#1-ordenamiento-burbuja-bubble-sort"&gt;1. Ordenamiento Burbuja (Bubble Sort)&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#el-proceso-paso-a-paso"&gt;El proceso paso a paso:&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#implementación-en-python"&gt;Implementación en Python:&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#eficiencia-de-bubble-sort"&gt;Eficiencia de Bubble Sort&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#2-ordenamiento-por-selección-selection-sort"&gt;2. Ordenamiento por Selección (Selection Sort)&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#el-proceso-paso-a-paso-1"&gt;El proceso paso a paso:&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#implementación-en-python-1"&gt;Implementación en Python:&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#eficiencia-de-selection-sort"&gt;Eficiencia de Selection Sort&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#3-optimizando-para-escenarios-optimistas-insertion-sort"&gt;3. Optimizando para Escenarios Optimistas (Insertion Sort)&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#el-proceso-paso-a-paso-2"&gt;El proceso paso a paso:&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#implementación-en-python-2"&gt;Implementación en Python:&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#la-gran-revelación-el-impacto-de-los-escenarios"&gt;La gran revelación: El impacto de los escenarios&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#por-qué-insertion-sort-es-tan-especial"&gt;¿Por qué Insertion Sort es tan especial?&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;¿Cómo podemos comparar dos algoritmos de manera formal? En el &lt;a href="https://blog.dacadev.com/programacion/estructura-datos-y-algoritmos/01-estructuras-de-datos-y-algoritmos-fundamentos"



 


&gt;post anterior&lt;/a&gt;, vimos que contar los segundos es una mala idea porque depende del hardware. Aprendimos que contar los &lt;strong&gt;pasos&lt;/strong&gt; es el camino correcto.&lt;/p&gt;
&lt;p&gt;Hoy aprenderemos a usar la &lt;strong&gt;Notación Big O&lt;/strong&gt;, el estándar que usamos en la industria para catalogar la eficiencia del software, y la aplicaremos analizando tres algoritmos de ordenamiento clásicos: &lt;strong&gt;Bubble Sort&lt;/strong&gt;, &lt;strong&gt;Selection Sort&lt;/strong&gt; e &lt;strong&gt;Insertion Sort&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="qué-es-la-notación-big-o"&gt;¿Qué es la Notación Big O?&lt;/h2&gt;
&lt;p&gt;La &lt;strong&gt;Notación Big O&lt;/strong&gt; es una herramienta matemática que describe la eficiencia de un algoritmo en función de cómo crece su número de pasos a medida que el tamaño de los datos de entrada (denotado como &lt;strong&gt;N&lt;/strong&gt;) aumenta.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;No nos dice la cantidad exacta de milisegundos que tardará un programa, sino &lt;strong&gt;la relación de crecimiento&lt;/strong&gt; entre el volumen de datos y el esfuerzo del procesador.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Los tres perfiles más comunes que hemos visto hasta ahora son:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;O(1) - Tiempo Constante&lt;/strong&gt;: El algoritmo siempre requiere la misma cantidad de pasos, sin importar si N es 10 o 10 millones (por ejemplo, leer un índice en un Array).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O(N) - Tiempo Lineal&lt;/strong&gt;: El número de pasos crece en proporción directa a los datos (por ejemplo, buscar un elemento mediante Búsqueda Lineal).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O(log N) - Tiempo Logarítmico&lt;/strong&gt;: El algoritmo es sumamente eficiente. Cada vez que duplicamos los datos, solo se agrega &lt;strong&gt;un paso&lt;/strong&gt; más al total (por ejemplo, la Búsqueda Binaria).&lt;/li&gt;
&lt;/ol&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;strong&gt;Nota matemática:&lt;/strong&gt; El logaritmo usado en Big O es en &lt;strong&gt;base 2&lt;/strong&gt; (log₂ N), no en base 10. Representa cuántas veces puedes dividir N a la mitad antes de llegar a 1.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Veamos gráficamente cómo se comparan estas curvas de crecimiento:&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 subgraph Eficiencia de Algoritmos
 direction TB
 C1[&amp;#34;Excelente: O(1)&amp;#34;]
 C2[&amp;#34;Muy Bueno: O(log N)&amp;#34;]
 C3[&amp;#34;Aceptable: O(N)&amp;#34;]
 C4[&amp;#34;Ineficiente: O(N²)&amp;#34;]
 end
&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Curvas de crecimiento de Big O&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-ordenamiento-burbuja-bubble-sort"&gt;1. Ordenamiento Burbuja (Bubble Sort)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Bubble Sort&lt;/strong&gt; es uno de los algoritmos de ordenamiento más simples e intuitivos. Se llama &amp;ldquo;Burbuja&amp;rdquo; porque los valores más altos van &amp;ldquo;flotando&amp;rdquo; gradualmente hacia el final del arreglo, como burbujas en el agua.&lt;/p&gt;
&lt;h3 id="el-proceso-paso-a-paso"&gt;El proceso paso a paso:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Apuntas a los dos primeros elementos consecutivos del arreglo.&lt;/li&gt;
&lt;li&gt;Si el de la izquierda es mayor que el de la derecha, los &lt;strong&gt;intercambias (swap)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Mueves los punteros una celda a la derecha y repites la comparación.&lt;/li&gt;
&lt;li&gt;Repites el proceso hasta llegar al final del arreglo. Al terminar esta primera pasada, el número más alto está garantizado a estar en la última celda.&lt;/li&gt;
&lt;li&gt;Regresas al inicio y realizas otra pasada completa.&lt;/li&gt;
&lt;li&gt;El proceso termina cuando completas una pasada entera &lt;strong&gt;sin realizar ningún intercambio&lt;/strong&gt;, lo que significa que todo está perfectamente ordenado.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 Start[&amp;#34;[4, 2, 7, 1]&amp;#34;] --&amp;gt; Step1[&amp;#34;Comparar 4 y 2 -&amp;gt; ¡Intercambiar!&amp;#34;]
 Step1 --&amp;gt; Step2[&amp;#34;[2, 4, 7, 1]&amp;#34;]
 Step2 --&amp;gt; Step3[&amp;#34;Comparar 4 y 7 -&amp;gt; No intercambiar&amp;#34;]
 Step3 --&amp;gt; Step4[&amp;#34;[2, 4, 7, 1]&amp;#34;]
 Step4 --&amp;gt; Step5[&amp;#34;Comparar 7 y 1 -&amp;gt; ¡Intercambiar!&amp;#34;]
 Step5 --&amp;gt; EndPass[&amp;#34;[2, 4, 1, 7] -&amp;gt; Primera pasada completada (7 está ordenado)&amp;#34;]
&lt;/pre&gt;

&lt;h3 id="implementación-en-python"&gt;Implementación en Python:&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;bubble_sort&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;]) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;unsorted_until_index&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;len&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;is_sorted&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;bool&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;while&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;not&lt;/span&gt; &lt;span style="color:#e06c75"&gt;is_sorted&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;is_sorted&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; &lt;span style="color:#e06c75"&gt;i&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;in&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;range&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;unsorted_until_index&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;i&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;i&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;+&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;# Intercambio rápido en Python:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;i&lt;/span&gt;], &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;i&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;+&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;i&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;+&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;], &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;i&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;is_sorted&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;unsorted_until_index&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;-=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="eficiencia-de-bubble-sort"&gt;Eficiencia de Bubble Sort&lt;/h3&gt;
&lt;p&gt;Para ordenar un arreglo de tamaño &lt;strong&gt;N&lt;/strong&gt;, en el peor de los casos realizamos aproximadamente &lt;strong&gt;N²&lt;/strong&gt; comparaciones e intercambios.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Complejidad&lt;/strong&gt;: &lt;strong&gt;O(N²)&lt;/strong&gt; o &lt;strong&gt;Tiempo Cuadrático&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Veredicto&lt;/strong&gt;: Altamente ineficiente para grandes conjuntos de datos. A medida que &lt;strong&gt;N&lt;/strong&gt; se duplica, el número de pasos se multiplica por &lt;strong&gt;cuatro&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="2-ordenamiento-por-selección-selection-sort"&gt;2. Ordenamiento por Selección (Selection Sort)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Selection Sort&lt;/strong&gt; toma un camino diferente: en lugar de ir comparando parejas consecutivas, realiza una pasada completa para &amp;ldquo;seleccionar&amp;rdquo; el elemento más pequeño del arreglo y colocarlo en su posición final.&lt;/p&gt;
&lt;h3 id="el-proceso-paso-a-paso-1"&gt;El proceso paso a paso:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Comienzas en el índice &lt;code&gt;0&lt;/code&gt;. Recorres todo el arreglo buscando el valor más pequeño.&lt;/li&gt;
&lt;li&gt;Al terminar la pasada, intercambias el valor más pequeño con el elemento en el índice &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Te mueves al índice &lt;code&gt;1&lt;/code&gt; y repites el proceso buscando el menor valor del resto del arreglo.&lt;/li&gt;
&lt;li&gt;Repites esto aumentando el índice de inicio en &lt;code&gt;1&lt;/code&gt; cada vez, hasta llegar al final.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 Start[&amp;#34;[4, 2, 7, 1]&amp;#34;] --&amp;gt; Step1[&amp;#34;Buscar el menor desde índice 0 -&amp;gt; Es 1&amp;#34;]
 Step1 --&amp;gt; Swap1[&amp;#34;Intercambiar 1 (menor) con 4 (índice 0)&amp;#34;]
 Swap1 --&amp;gt; Step2[&amp;#34;[1, 2, 7, 4]&amp;#34;]
 Step2 --&amp;gt; Step3[&amp;#34;Buscar el menor desde índice 1 -&amp;gt; Es 2&amp;#34;]
 Step3 --&amp;gt; Swap2[&amp;#34;2 ya está en su lugar -&amp;gt; No hay cambios&amp;#34;]
 Swap2 --&amp;gt; Step4[&amp;#34;[1, 2, 7, 4]&amp;#34;]
 Step4 --&amp;gt; Step5[&amp;#34;Buscar el menor desde índice 2 -&amp;gt; Es 4&amp;#34;]
 Step5 --&amp;gt; Swap3[&amp;#34;Intercambiar 4 con 7 (índice 2)&amp;#34;]
 Swap3 --&amp;gt; End[&amp;#34;[1, 2, 4, 7] -&amp;gt; ¡Completamente Ordenado! 🎉&amp;#34;]
&lt;/pre&gt;

&lt;h3 id="implementación-en-python-1"&gt;Implementación en Python:&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;selection_sort&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;]) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; &lt;span style="color:#e06c75"&gt;i&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;in&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;range&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;len&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;lowest_number_index&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;i&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; &lt;span style="color:#e06c75"&gt;j&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;in&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;range&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;i&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;len&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;)):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;j&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;lowest_number_index&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;lowest_number_index&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;j&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; &lt;span style="color:#e06c75"&gt;lowest_number_index&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;!=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;i&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;i&lt;/span&gt;], &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;lowest_number_index&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;lowest_number_index&lt;/span&gt;], &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;i&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="eficiencia-de-selection-sort"&gt;Eficiencia de Selection Sort&lt;/h3&gt;
&lt;p&gt;Si contamos los pasos de Selection Sort, en promedio realiza unas N²/2 comparaciones. Sin embargo, dado que &lt;strong&gt;Big O elimina las constantes&lt;/strong&gt; (las fracciones y multiplicaciones por números fijos), su complejidad teórica también queda como &lt;strong&gt;O(N²)&lt;/strong&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;strong&gt;¿Selection Sort o Bubble Sort?&lt;/strong&gt; Aunque ambos son categorizados bajo el mismo grupo O(N²), Selection Sort es aproximadamente &lt;strong&gt;el doble de rápido&lt;/strong&gt; en la vida real porque realiza un máximo de N intercambios, mientras que Bubble Sort puede realizar hasta N² intercambios.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;hr&gt;
&lt;h2 id="3-optimizando-para-escenarios-optimistas-insertion-sort"&gt;3. Optimizando para Escenarios Optimistas (Insertion Sort)&lt;/h2&gt;
&lt;p&gt;Hasta ahora hemos analizado el rendimiento basándonos en el &lt;strong&gt;peor caso posible&lt;/strong&gt;. Pero en el desarrollo real, muchas veces nos encontramos con arreglos que ya están parcialmente ordenados. Aquí es donde brilla &lt;strong&gt;Insertion Sort&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Insertion Sort&lt;/strong&gt; funciona de manera similar a como ordenarías un mazo de cartas en tu mano.&lt;/p&gt;
&lt;h3 id="el-proceso-paso-a-paso-2"&gt;El proceso paso a paso:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Comienzas en el índice &lt;code&gt;1&lt;/code&gt; (la segunda celda). Remueves temporalmente el valor y lo guardas en una variable temporal (&lt;code&gt;temp&lt;/code&gt;), dejando un &amp;ldquo;hueco&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Comparas cada elemento a la izquierda del hueco con el valor en &lt;code&gt;temp&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Si el elemento de la izquierda es mayor que &lt;code&gt;temp&lt;/code&gt;, lo desplazas una posición hacia la derecha (el hueco se mueve hacia la izquierda).&lt;/li&gt;
&lt;li&gt;Repites el paso 3 hasta encontrar un elemento menor o igual a &lt;code&gt;temp&lt;/code&gt;, o llegar al inicio del arreglo.&lt;/li&gt;
&lt;li&gt;Colocas el valor de &lt;code&gt;temp&lt;/code&gt; en el hueco actual.&lt;/li&gt;
&lt;li&gt;Repites el ciclo avanzando al siguiente índice.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="implementación-en-python-2"&gt;Implementación en Python:&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;insertion_sort&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;]) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; &lt;span style="color:#e06c75"&gt;index&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;in&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;range&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;len&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;)):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;temp_value&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;index&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;position&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;index&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;-&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;while&lt;/span&gt; &lt;span style="color:#e06c75"&gt;position&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;position&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;temp_value&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;position&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;position&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;position&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;-=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;position&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;temp_value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;arr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="la-gran-revelación-el-impacto-de-los-escenarios"&gt;La gran revelación: El impacto de los escenarios&lt;/h2&gt;
&lt;p&gt;Analicemos la eficiencia de los tres algoritmos comparando sus mejores, peores y promedio casos:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Algoritmo&lt;/th&gt;
 &lt;th&gt;Peor Caso (Worst Case)&lt;/th&gt;
 &lt;th&gt;Caso Promedio (Average)&lt;/th&gt;
 &lt;th&gt;Mejor Caso (Best Case)&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Bubble Sort&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;O(N²)&lt;/td&gt;
 &lt;td&gt;O(N²)&lt;/td&gt;
 &lt;td&gt;O(N) (si ya está ordenado)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Selection Sort&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;O(N²)&lt;/td&gt;
 &lt;td&gt;O(N²)&lt;/td&gt;
 &lt;td&gt;O(N²)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Insertion Sort&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;O(N²)&lt;/td&gt;
 &lt;td&gt;O(N²)&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;O(N)&lt;/strong&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="por-qué-insertion-sort-es-tan-especial"&gt;¿Por qué Insertion Sort es tan especial?&lt;/h3&gt;
&lt;p&gt;Si le pasamos un arreglo que &lt;strong&gt;ya está ordenado&lt;/strong&gt; a Insertion Sort, el bucle &lt;code&gt;while&lt;/code&gt; interno se rompe inmediatamente en el primer paso (&lt;code&gt;break&lt;/code&gt;). No hace ningún desplazamiento de datos. Por lo tanto, se ejecuta en un espectacular &lt;strong&gt;tiempo lineal O(N)&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Si tus datos están mayoritariamente ordenados, &lt;strong&gt;Insertion Sort es por mucho la mejor opción&lt;/strong&gt; entre los ordenamientos básicos.&lt;/p&gt;</content:encoded></item><item><title>Sistemas Agénticos: El Espectro de Autonomía y Desarrollo Responsable</title><link>https://blog.dacadev.com/generative-ai/agents/sistemas-agenticos-autonomia/</link><pubDate>Mon, 18 May 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/generative-ai/agents/sistemas-agenticos-autonomia/</guid><dc:creator>Dacadev</dc:creator><category>IA generativa</category><description>Aprende qué es un sistema agéntico, explora el espectro de autonomía desde prompting hasta agentes autónomos, y descubre cómo evaluarlos y desarrollarlos con seguridad.</description><media:content url="https://blog.dacadev.com/images/generative-ai/agents/02-sistemas-agenticos/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#qué-es-un-sistema-agéntico"&gt;¿Qué es un Sistema Agéntico?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#el-espectro-de-autonomía"&gt;El Espectro de Autonomía&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#nivel-1-prompting-estándar-baja-autonomía"&gt;Nivel 1: Prompting Estándar (Baja Autonomía)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#nivel-2-pasos-fijos-autonomía-orquestada--rag"&gt;Nivel 2: Pasos Fijos (Autonomía Orquestada / RAG)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#nivel-3-agente-autónomo-alta-autonomía"&gt;Nivel 3: Agente Autónomo (Alta Autonomía)&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#casos-de-uso-del-mundo-real"&gt;Casos de Uso del Mundo Real&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#desarrollo-y-uso-responsable-de-agentes-ia"&gt;Desarrollo y Uso Responsable de Agentes IA&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#1-humano-en-el-bucle-human-in-the-loop"&gt;1. Humano en el Bucle (Human-in-the-Loop)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#2-guardrails-límites-y-barreras-técnicas"&gt;2. Guardrails (Límites y Barreras Técnicas)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#3-mitigación-de-desinformación-y-sesgos"&gt;3. Mitigación de Desinformación y Sesgos&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#evaluando-sistemas-agénticos-un-desafío-complejo"&gt;Evaluando Sistemas Agénticos: Un Desafío Complejo&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Cuando empezamos a programar con &lt;strong&gt;LLMs&lt;/strong&gt; (Large Language Models), a menudo nos quedamos en la fase de &amp;ldquo;pregunta-respuesta&amp;rdquo;. Le envías un prompt al modelo y este te devuelve una respuesta inmediata. Pero el verdadero poder de la &lt;strong&gt;Inteligencia Artificial&lt;/strong&gt; (IA) surge cuando le damos libertad al modelo para actuar por sí mismo, tomar decisiones y corregir su camino.&lt;/p&gt;
&lt;p&gt;Aquí es donde entramos al tema de los &lt;strong&gt;Sistemas Agénticos&lt;/strong&gt;. Te has preguntado:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;¿cuánta libertad debería tener realmente una IA?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;¿Cómo nos aseguramos de que no tome acciones destructivas?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;¿Cómo medimos si está haciendo bien su trabajo?&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;En este artículo aprenderás qué define a un sistema agéntico, exploraremos el espectro de autonomía desde un simple prompt hasta agentes 100% autónomos, y analizaremos las mejores prácticas de desarrollo responsable y evaluación de sistemas agénticos. 🚀&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;hr&gt;
&lt;h2 id="qué-es-un-sistema-agéntico"&gt;¿Qué es un Sistema Agéntico?&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Un sistema se considera &lt;strong&gt;agéntico&lt;/strong&gt; en la medida en que el LLM tiene el control para tomar decisiones, elegir herramientas y definir los pasos a seguir para alcanzar un objetivo.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A diferencia de un software tradicional basado puramente en reglas rígidas y flujos de control fijos (&lt;code&gt;if/else&lt;/code&gt;), un sistema agéntico exhibe un &lt;strong&gt;comportamiento orientado a metas&lt;/strong&gt; (goal-directed behavior). Nosotros le decimos el &lt;em&gt;qué&lt;/em&gt; (el objetivo final) y el agente decide el &lt;em&gt;cómo&lt;/em&gt; (el plan de ejecución).&lt;/p&gt;
&lt;p&gt;No obstante, la autonomía no es un interruptor binario de &amp;ldquo;todo o nada&amp;rdquo;. Existe un amplio espectro de control que podemos otorgar a nuestros agentes, dependiendo de la criticidad de la tarea y de los límites que queramos establecer.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="el-espectro-de-autonomía"&gt;El Espectro de Autonomía&lt;/h2&gt;
&lt;p&gt;Dependiendo del diseño del sistema, un agente de IA puede tener diferentes grados de libertad. En la práctica, podemos clasificar la autonomía en tres grandes niveles:&lt;/p&gt;
&lt;h3 id="nivel-1-prompting-estándar-baja-autonomía"&gt;Nivel 1: Prompting Estándar (Baja Autonomía)&lt;/h3&gt;
&lt;p&gt;Es el nivel básico. El usuario envía un prompt, el LLM procesa la solicitud utilizando únicamente su conocimiento interno y genera una respuesta directa. No hay uso de herramientas externas ni toma de decisiones sobre el flujo de ejecución. El control es 100% del usuario.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 P[User Prompt] --&amp;gt; LLM[🧠 LLM Tradicional] --&amp;gt; Ans1[Respuesta Directa]
&lt;/pre&gt;

&lt;h3 id="nivel-2-pasos-fijos-autonomía-orquestada--rag"&gt;Nivel 2: Pasos Fijos (Autonomía Orquestada / RAG)&lt;/h3&gt;
&lt;p&gt;En este nivel, el agente está integrado dentro de un flujo de trabajo predefinido (orquestado). Por ejemplo, un sistema &lt;strong&gt;RAG&lt;/strong&gt; (Generación Aumentada por Recuperación) primero ejecuta una búsqueda vectorial en una base de datos de manera obligatoria (Paso 1) y luego le pasa ese contexto al LLM para que redacte la respuesta final (Paso 2). El modelo tiene cierta autonomía para elegir herramientas locales o resumir la información, pero no puede alterar el flujo global de los pasos.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 P2[User Prompt] --&amp;gt; S1[🔍 Paso 1: Búsqueda Vectorial]
 S1 --&amp;gt; S2[🧠 Paso 2: Razonamiento y Herramientas]
 S2 --&amp;gt; Ans2[Respuesta Final]
&lt;/pre&gt;

&lt;h3 id="nivel-3-agente-autónomo-alta-autonomía"&gt;Nivel 3: Agente Autónomo (Alta Autonomía)&lt;/h3&gt;
&lt;p&gt;Aquí el agente tiene total libertad dentro de un bucle de ejecución interactivo. El LLM recibe una meta, genera un plan inicial, ejecuta una acción (como llamar a una API o ejecutar código), observa el resultado del entorno, actualiza su plan y decide de forma autónoma si ha logrado cumplir el objetivo o si necesita seguir iterando.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 P3[User Prompt] --&amp;gt; RLLM[🧠 LLM - Memoria y Herramientas]
 RLLM --&amp;gt; Plan[📋 Generar Plan]
 Plan --&amp;gt; Action[⚙️ Ejecutar Acción]
 Action --&amp;gt; Observe[👁️ Observar Resultado]
 Observe --&amp;gt; Decision{¿Meta cumplida?}
 Decision --&amp;gt;|No: Re-planificar| Update[🔄 Actualizar Plan]
 Update --&amp;gt; RLLM
 Decision --&amp;gt;|Sí| Ans3[Respuesta Final]
&lt;/pre&gt;

&lt;hr&gt;
&lt;h2 id="casos-de-uso-del-mundo-real"&gt;Casos de Uso del Mundo Real&lt;/h2&gt;
&lt;p&gt;Los sistemas agénticos ya están transformando múltiples industrias. Algunos de los ejemplos más destacados son:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Coding Agents (Agentes de Programación)&lt;/strong&gt;: Herramientas que no solo sugieren código, sino que pueden leer repositorios enteros, escribir pruebas unitarias, ejecutar programas en entornos de prueba seguros (sandboxes) y depurar errores por sí mismos hasta que el código funcione.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Búsqueda Profunda (DeepSearch)&lt;/strong&gt;: Agentes de investigación que realizan búsquedas web iterativas, cruzando múltiples fuentes de información, validando datos contradictorios y redactando reportes completos de manera autónoma.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatización de Procesos de Negocio&lt;/strong&gt;: Agentes capaces de interactuar con software de facturación, responder correos electrónicos de clientes resolviendo problemas complejos y actualizar bases de datos sin intervención humana constante.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="desarrollo-y-uso-responsable-de-agentes-ia"&gt;Desarrollo y Uso Responsable de Agentes IA&lt;/h2&gt;
&lt;p&gt;Darle autonomía a un agente digital conlleva grandes riesgos. Si le permites a un agente ejecutar comandos en tu terminal o enviar correos a tus clientes, un pequeño error de razonamiento o una alucinación podría causar pérdidas de información o daños reputacionales.&lt;/p&gt;
&lt;p&gt;Por ello, el desarrollo ético y seguro de agentes requiere la implementación de tres pilares fundamentales:&lt;/p&gt;
&lt;h3 id="1-humano-en-el-bucle-human-in-the-loop"&gt;1. Humano en el Bucle (Human-in-the-Loop)&lt;/h3&gt;
&lt;p&gt;Consiste en diseñar puntos de control donde el agente deba detener su ejecución y solicitar la aprobación explícita de un ser humano antes de realizar acciones críticas o irreversibles.&lt;/p&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;strong&gt;Regla de oro:&lt;/strong&gt; Si una acción del agente tiene efectos directos en el mundo físico o digital real (ej. realizar un pago, enviar un email a un cliente, o borrar un archivo), &lt;strong&gt;siempre&lt;/strong&gt; debes implementar una aprobación humana previa. 🚀&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id="2-guardrails-límites-y-barreras-técnicas"&gt;2. Guardrails (Límites y Barreras Técnicas)&lt;/h3&gt;
&lt;p&gt;Los guardrails son capas de software que rodean al agente y restringen lo que puede y no puede hacer. Algunas estrategias eficaces incluyen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Validación Estricta de Entradas y Salidas&lt;/strong&gt;: Analizar y limpiar los prompts enviados al LLM y las llamadas a herramientas generadas por este.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Presupuesto de Tokens y Pasos&lt;/strong&gt;: Limitar el número de iteraciones máximas del bucle autónomo para evitar bucles infinitos muy costosos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Entornos Seguros (Sandboxing)&lt;/strong&gt;: Ejecutar cualquier herramienta de código o comando del sistema dentro de contenedores aislados (como Docker) para proteger la máquina anfitriona.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-mitigación-de-desinformación-y-sesgos"&gt;3. Mitigación de Desinformación y Sesgos&lt;/h3&gt;
&lt;p&gt;Los agentes pueden propagar información falsa rápidamente si no se controlan sus fuentes de datos. Es vital dotar al agente de capacidades de contraste y verificación de datos cuando trabaja en entornos abiertos como internet, además de que de por si un LLM puede alucinar, dando respuestas que suenan plausibles pero son completamente inventadas.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="evaluando-sistemas-agénticos-un-desafío-complejo"&gt;Evaluando Sistemas Agénticos: Un Desafío Complejo&lt;/h2&gt;
&lt;p&gt;Si evaluar un LLM tradicional (que solo produce texto) ya es difícil, evaluar un agente es considerablemente más complejo. Un agente interactúa con su entorno, ejecuta múltiples pasos lógicos y toma decisiones secuenciales donde cada acción influye en el siguiente estado del sistema.&lt;/p&gt;
&lt;p&gt;Al evaluar sistemas agénticos, no podemos limitarnos a verificar si el texto final &amp;ldquo;se lee bien&amp;rdquo;. Debemos evaluar el &lt;strong&gt;sistema completo&lt;/strong&gt; bajo múltiples dimensiones:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;Dimensión de Evaluación&lt;/th&gt;
 &lt;th style="text-align: left"&gt;Qué mide&lt;/th&gt;
 &lt;th style="text-align: left"&gt;Cómo se evalúa&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Tasa de Éxito de la Tarea&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Si el agente logró resolver la meta propuesta correctamente.&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Pruebas de integración automatizadas con metas claras y verificables.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Eficiencia de la Trayectoria&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;El número de pasos y tokens utilizados. Un agente que resuelve el problema en 3 pasos es mejor que uno que toma 20.&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Análisis de logs de ejecución y costos asociados.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Alineación y Cumplimiento&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Si el agente respetó las políticas de seguridad y las barreras técnicas durante su ejecución.&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Inyección de prompts maliciosos de prueba (Red Teaming).&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;&lt;strong&gt;Resiliencia ante Errores&lt;/strong&gt;&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Cómo reacciona el agente cuando una herramienta falla o una API devuelve un código de error.&lt;/td&gt;
 &lt;td style="text-align: left"&gt;Simulación de caídas de servicios y análisis de la capacidad de replanificación del agente.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;La evaluación constante es la única forma de garantizar que el agente sea seguro, confiable y verdaderamente útil antes de desplegarlo en un entorno de producción crítico.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;La autonomía de los agentes de IA abre un mundo lleno de posibilidades, pero también exige un alto nivel de responsabilidad de nuestra parte como desarrolladores. Al comprender el &lt;strong&gt;espectro de autonomía&lt;/strong&gt;, diseñar e implementar &lt;strong&gt;guardrails&lt;/strong&gt; técnicos sólidos e implementar metodologías de &lt;strong&gt;evaluación robustas&lt;/strong&gt;, podemos construir herramientas agénticas que asombren a nuestros usuarios a la vez que se mantienen totalmente seguras.&lt;/p&gt;
&lt;p&gt;En la próxima entrega de esta serie, exploraremos cómo podemos escalar estos sistemas haciendo que múltiples agentes con especialidades únicas colaboren entre sí. ¡Nos vemos en el próximo artículo!&lt;/p&gt;</content:encoded></item><item><title>Estructuras de Datos y Algoritmos: Los Fundamentos que Todo Dev Debe Saber</title><link>https://blog.dacadev.com/programacion/estructura-datos-y-algoritmos/01-estructuras-de-datos-y-algoritmos-fundamentos/</link><pubDate>Sun, 17 May 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/programacion/estructura-datos-y-algoritmos/01-estructuras-de-datos-y-algoritmos-fundamentos/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Descubre por qué importan las estructuras de datos y cómo medir su eficiencia en pasos en lugar de segundos. Guía completa de Arrays, Sets y Búsqueda Binaria.</description><media:content url="https://blog.dacadev.com/images/programming/structures-algorithms/01-structures-algorithms-fundamentals/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#por-qué-importa-la-estructura"&gt;¿Por qué importa la estructura?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#qué-es-una-estructura-de-datos"&gt;¿Qué es una Estructura de Datos?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#midiendo-la-velocidad-del-código"&gt;Midiendo la velocidad del código&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#el-array"&gt;El Array&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#las-4-operaciones-fundamentales-en-un-array"&gt;Las 4 Operaciones Fundamentales en un Array&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#1-lectura-read--get"&gt;1. Lectura (Read / Get)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#2-búsqueda-search"&gt;2. Búsqueda (Search)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#3-inserción-insert"&gt;3. Inserción (Insert)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#4-eliminación-delete"&gt;4. Eliminación (Delete)&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#sets-cómo-una-sola-regla-cambia-toda-la-eficiencia"&gt;Sets: Cómo una sola regla cambia toda la eficiencia&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#arreglos-ordenados"&gt;Arreglos Ordenados&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#inserción-en-arreglos-ordenados"&gt;Inserción en Arreglos Ordenados&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#búsqueda-binaria"&gt;Búsqueda Binaria&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#búsqueda-binaria-vs-búsqueda-lineal"&gt;Búsqueda Binaria vs. Búsqueda Lineal&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Si estás dando tus primeros pasos en el desarrollo de software, es muy común que midas el éxito de tu código con una única pregunta: &lt;strong&gt;¿funciona y hace lo que se supone que debe hacer?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sin embargo, a medida que avanzas en tu carrera, te das cuenta de que existe un mundo entero de otras métricas críticas, como por ejemplo: &lt;em&gt;¿Qué tan rápido se ejecuta?&lt;/em&gt; &lt;em&gt;¿Cuánta memoria consume?&lt;/em&gt; &lt;em&gt;¿Es escalable si el volumen de datos crece por mil?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Para escribir código que no solo funcione sino que sea verdaderamente profesional, debes dominar dos pilares fundamentales: las &lt;strong&gt;estructuras de datos&lt;/strong&gt; y los &lt;strong&gt;algoritmos&lt;/strong&gt;. Empecemos por lo básico: ¿qué son y por qué importan?&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="por-qué-importa-la-estructura"&gt;¿Por qué importa la estructura?&lt;/h2&gt;
&lt;p&gt;Consideremos una tarea sencilla: escribir una función en Python que imprima todos los números pares del 2 al 100.&lt;/p&gt;
&lt;p&gt;Aquí tienes la &lt;strong&gt;versión uno&lt;/strong&gt; (menos eficiente):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;print_numbers_version_one&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;number&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;while&lt;/span&gt; &lt;span style="color:#e06c75"&gt;number&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;100&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;# Si el número es par, lo imprimimos:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; &lt;span style="color:#e06c75"&gt;number&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;%&lt;/span&gt; &lt;span style="color:#d19a66"&gt;2&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;==&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;number&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;number&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Y aquí tienes la &lt;strong&gt;versión dos&lt;/strong&gt; (más eficiente):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;print_numbers_version_two&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;number&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;while&lt;/span&gt; &lt;span style="color:#e06c75"&gt;number&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;100&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;number&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;# Incrementamos por 2 directo al siguiente número par:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;number&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ambos programas producen exactamente el mismo resultado. Pero la versión uno realiza &lt;strong&gt;100 iteraciones&lt;/strong&gt; y comprueba la paridad en cada paso. La versión dos solo hace &lt;strong&gt;50 iteraciones&lt;/strong&gt; y no realiza comprobaciones matemáticas innecesarias. Es el doble de eficiente.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="qué-es-una-estructura-de-datos"&gt;¿Qué es una Estructura de Datos?&lt;/h2&gt;
&lt;p&gt;Una &lt;strong&gt;estructura de datos&lt;/strong&gt; es la manera física y lógica en la que &lt;strong&gt;organizamos&lt;/strong&gt;, &lt;strong&gt;gestionamos&lt;/strong&gt; y &lt;strong&gt;almacenamos&lt;/strong&gt; los datos en nuestro código. La forma en que eliges organizar tus datos afecta directamente la rapidez con la que tu programa puede operar con ellos.&lt;/p&gt;
&lt;p&gt;Para un mismo propósito, puedes usar diferentes estructuras. Por ejemplo, si deseas unir tres palabras:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Usando variables simples&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;x&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;¡Hola! &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;y&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;¿Cómo estás &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;z&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;hoy?&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;x&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;y&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;z&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Usando un Array (o Lista en Python)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;array&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#34;¡Hola! &amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;¿Cómo estás &amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;hoy?&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;array&lt;/span&gt;[&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;array&lt;/span&gt;[&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;array&lt;/span&gt;[&lt;span style="color:#d19a66"&gt;2&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="midiendo-la-velocidad-del-código"&gt;Midiendo la velocidad del código&lt;/h2&gt;
&lt;p&gt;Un error clásico es medir la velocidad de un programa cronometrando los segundos que tarda en completarse. &lt;strong&gt;No es la mejor manera&lt;/strong&gt;, El tiempo de ejecución en segundos varía según:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;El procesador y hardware de la máquina.&lt;/li&gt;
&lt;li&gt;Qué otros programas se están ejecutando en segundo plano.&lt;/li&gt;
&lt;li&gt;El lenguaje de programación y su compilador o intérprete.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Para medir la velocidad de manera científica y objetiva, contamos &lt;strong&gt;la cantidad de pasos físicos&lt;/strong&gt; que requiere un algoritmo para completarse.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="el-array"&gt;El Array&lt;/h2&gt;
&lt;p&gt;El &lt;strong&gt;Array&lt;/strong&gt; (o arreglo) es la estructura de datos más básica y el punto de partida de casi todo en computación. Físicamente, un array es un bloque &lt;strong&gt;continuo&lt;/strong&gt; de memoria.&lt;/p&gt;
&lt;p&gt;Un array tiene dos características clave:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Tamaño (Size)&lt;/strong&gt;: El número total de elementos que contiene.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Índice (Index)&lt;/strong&gt;: La posición numérica de cada celda. En la gran mayoría de lenguajes de programación, empezamos a contar desde &lt;strong&gt;0&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;array&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#34;manzanas&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;bananas&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;pepinos&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;dátiles&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;arándanos&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Podemos representar la memoria de un array así:&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 a0[&amp;#34;[0] manzanas&amp;lt;br/&amp;gt;Mem: 1000&amp;#34;]
 a1[&amp;#34;[1] bananas&amp;lt;br/&amp;gt;Mem: 1001&amp;#34;]
 a2[&amp;#34;[2] pepinos&amp;lt;br/&amp;gt;Mem: 1002&amp;#34;]
 a3[&amp;#34;[3] dátiles&amp;lt;br/&amp;gt;Mem: 1003&amp;#34;]
 a4[&amp;#34;[4] arándanos&amp;lt;br/&amp;gt;Mem: 1004&amp;#34;]
 a0 --- a1 --- a2 --- a3 --- a4
&lt;/pre&gt;

&lt;h3 id="las-4-operaciones-fundamentales-en-un-array"&gt;Las 4 Operaciones Fundamentales en un Array&lt;/h3&gt;
&lt;p&gt;Para evaluar qué tan eficiente es una estructura de datos, analizamos cuántos pasos le toma realizar las cuatro operaciones básicas:&lt;/p&gt;
&lt;h4 id="1-lectura-read--get"&gt;1. Lectura (Read / Get)&lt;/h4&gt;
&lt;p&gt;Consiste en obtener el valor que está en un índice específico (por ejemplo, &amp;ldquo;¿qué hay en la posición 3?&amp;rdquo;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;¿Cómo lo hace la computadora?&lt;/strong&gt; Al estar guardados en memoria de manera continua, la computadora hace un cálculo matemático simple: &lt;code&gt;DirecciónInicio + (Índice * TamañoCelda)&lt;/code&gt;. Va directo a la celda en &lt;strong&gt;1 paso&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Eficiencia&lt;/strong&gt;: 1 paso (constante).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="2-búsqueda-search"&gt;2. Búsqueda (Search)&lt;/h4&gt;
&lt;p&gt;Consiste en encontrar el índice de un elemento sabiendo únicamente su valor (por ejemplo, &amp;ldquo;¿en qué posición están los &amp;lsquo;pepinos&amp;rsquo;?&amp;rdquo;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;¿Cómo lo hace?&lt;/strong&gt; La computadora no puede ver el contenido de todo el array a la vez. Debe ir celda por celda, de izquierda a derecha, comprobando si el valor coincide. A esto se le llama &lt;strong&gt;Búsqueda Lineal&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Eficiencia&lt;/strong&gt;: Si el elemento está al principio, toma 1 paso. Si está al final o no existe, toma &lt;strong&gt;N pasos&lt;/strong&gt; (siendo N el tamaño del array). En el peor de los casos, la eficiencia es de &lt;strong&gt;N pasos&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="3-inserción-insert"&gt;3. Inserción (Insert)&lt;/h4&gt;
&lt;p&gt;Consiste en agregar un nuevo elemento al array. Aquí tenemos dos escenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Insertar al final&lt;/strong&gt;: Es súper sencillo. La computadora simplemente coloca el valor en la siguiente celda libre. Toma &lt;strong&gt;1 paso&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Insertar al inicio o en medio&lt;/strong&gt;: ¡Aquí viene el dolor de cabeza! Para meter un valor al inicio (índice 0), primero debemos mover &lt;strong&gt;todos&lt;/strong&gt; los elementos existentes una celda hacia la derecha para abrir espacio.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 subgraph Antes de Insertar
 A0[&amp;#34;[0] A&amp;#34;] --&amp;gt; A1[&amp;#34;[1] B&amp;#34;] --&amp;gt; A2[&amp;#34;[2] C&amp;#34;]
 end
 subgraph Proceso de Desplazamiento
 D0[&amp;#34;Desplazar C a [3]&amp;#34;] --&amp;gt; D1[&amp;#34;Desplazar B a [2]&amp;#34;] --&amp;gt; D2[&amp;#34;Desplazar A a [1]&amp;#34;]
 end
 subgraph Resultado Final
 R0[&amp;#34;[0] NUEVO&amp;#34;] --&amp;gt; R1[&amp;#34;[1] A&amp;#34;] --&amp;gt; R2[&amp;#34;[2] B&amp;#34;] --&amp;gt; R3[&amp;#34;[3] C&amp;#34;]
 end
&lt;/pre&gt;

&lt;p&gt;Si el array tiene tamaño N, insertar al principio toma &lt;strong&gt;N desplazamientos + 1 inserción = N + 1 pasos&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id="4-eliminación-delete"&gt;4. Eliminación (Delete)&lt;/h4&gt;
&lt;p&gt;Consiste en borrar un elemento de un índice específico. Al igual que con la inserción, si borramos el elemento del inicio, dejamos un &amp;ldquo;hueco vacío&amp;rdquo;. Las reglas de los arrays exigen que no haya espacios vacíos intermedios, por lo que debemos desplazar &lt;strong&gt;todos&lt;/strong&gt; los elementos de la derecha una posición hacia la izquierda.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Eficiencia&lt;/strong&gt;: En el peor de los casos (eliminar el primer elemento), toma &lt;strong&gt;N - 1 pasos&lt;/strong&gt; de desplazamiento.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="sets-cómo-una-sola-regla-cambia-toda-la-eficiencia"&gt;Sets: Cómo una sola regla cambia toda la eficiencia&lt;/h2&gt;
&lt;p&gt;Un &lt;strong&gt;Set&lt;/strong&gt; (conjunto) es un tipo especial de arreglo con una regla estricta: &lt;strong&gt;no se permiten valores duplicados&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Esta pequeña regla de negocio transforma drásticamente la eficiencia de la operación de &lt;strong&gt;inserción&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;En un Array común, insertar al final toma &lt;strong&gt;1 paso&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;En un Set, antes de insertar un elemento al final, la computadora debe hacer una &lt;strong&gt;búsqueda lineal completa&lt;/strong&gt; para asegurar que el elemento no exista previamente en el Set.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Por lo tanto, la inserción al final en un Set toma &lt;strong&gt;N pasos de búsqueda + 1 paso de inserción = N + 1 pasos&lt;/strong&gt;.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Aunque los Sets protegen la integridad de tus datos previniendo duplicados, debes tener en cuenta que su inserción es mucho más lenta en arreglos de gran tamaño.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;hr&gt;
&lt;h2 id="arreglos-ordenados"&gt;Arreglos Ordenados&lt;/h2&gt;
&lt;p&gt;Un &lt;strong&gt;Arreglo Ordenado&lt;/strong&gt; es un array cuyos valores se mantienen de forma ascendente o descendente de forma obligatoria.&lt;/p&gt;
&lt;h3 id="inserción-en-arreglos-ordenados"&gt;Inserción en Arreglos Ordenados&lt;/h3&gt;
&lt;p&gt;Para insertar un valor en un arreglo ordenado (por ejemplo, meter el número &lt;code&gt;4&lt;/code&gt; en &lt;code&gt;[1, 3, 5, 8]&lt;/code&gt;), no podemos simplemente agregarlo al final. Debemos:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Buscar el lugar exacto donde corresponde el elemento para mantener el orden (después del &lt;code&gt;3&lt;/code&gt; y antes del &lt;code&gt;5&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Desplazar los elementos mayores hacia la derecha (&lt;code&gt;5&lt;/code&gt; y &lt;code&gt;8&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Insertar el nuevo valor.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Esto hace que la inserción sea ligeramente más costosa en pasos que en un array normal, pero abre la puerta a un algoritmo de búsqueda revolucionario.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="búsqueda-binaria"&gt;Búsqueda Binaria&lt;/h2&gt;
&lt;p&gt;Si tu arreglo &lt;strong&gt;no está ordenado&lt;/strong&gt;, la única forma de buscar es la búsqueda lineal (celda por celda), lo que toma hasta &lt;strong&gt;N&lt;/strong&gt; pasos.&lt;/p&gt;
&lt;p&gt;Pero si tu arreglo &lt;strong&gt;sí está ordenado&lt;/strong&gt;, puedes usar la &lt;strong&gt;Búsqueda Binaria&lt;/strong&gt;. Este algoritmo consiste en:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ir directo al elemento del medio del arreglo.&lt;/li&gt;
&lt;li&gt;Si el valor buscado es menor, descartas toda la mitad derecha.&lt;/li&gt;
&lt;li&gt;Si es mayor, descartas toda la mitad izquierda.&lt;/li&gt;
&lt;li&gt;Repites el proceso en la mitad restante hasta encontrarlo o quedarte sin elementos.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 Start[&amp;#34;Buscar 11 en [2, 4, 6, 8, 11, 14, 18, 22]&amp;#34;] --&amp;gt; Step1[&amp;#34;Valor central: 8 (índice 3)&amp;#34;]
 Step1 --&amp;gt; Check{&amp;#34;¿Es 11 == 8?&amp;#34;}
 Check -- No, es mayor --&amp;gt; DescartarIzq[&amp;#34;Descartar [2, 4, 6, 8]&amp;#34;]
 DescartarIzq --&amp;gt; SubSearch[&amp;#34;Buscar en [11, 14, 18, 22]&amp;#34;]
 SubSearch --&amp;gt; Step2[&amp;#34;Valor central: 14 (índice 5)&amp;#34;]
 Step2 --&amp;gt; Check2{&amp;#34;¿Es 11 == 14?&amp;#34;}
 Check2 -- No, es menor --&amp;gt; DescartarDer[&amp;#34;Descartar [14, 18, 22]&amp;#34;]
 DescartarDer --&amp;gt; Final[&amp;#34;Buscar en [11] -&amp;gt; ¡Encontrado! 🎉&amp;#34;]
&lt;/pre&gt;

&lt;h3 id="búsqueda-binaria-vs-búsqueda-lineal"&gt;Búsqueda Binaria vs. Búsqueda Lineal&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Tamaño del Arreglo (N)&lt;/th&gt;
 &lt;th&gt;Pasos Máximos (Lineal)&lt;/th&gt;
 &lt;th&gt;Pasos Máximos (Binaria)&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;8&lt;/td&gt;
 &lt;td&gt;8&lt;/td&gt;
 &lt;td&gt;3&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;100&lt;/td&gt;
 &lt;td&gt;100&lt;/td&gt;
 &lt;td&gt;7&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;10,000&lt;/td&gt;
 &lt;td&gt;10,000&lt;/td&gt;
 &lt;td&gt;14&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;1,000,000&lt;/td&gt;
 &lt;td&gt;1,000,000&lt;/td&gt;
 &lt;td&gt;20&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;La diferencia es notable. Buscar en una base de datos de un millón de registros toma &lt;strong&gt;un millón de pasos&lt;/strong&gt; con búsqueda lineal, pero solo &lt;strong&gt;20 pasos&lt;/strong&gt; usando búsqueda binaria. Por eso, elegir el algoritmo correcto de acuerdo a la estructura de tus datos marca toda la diferencia del mundo.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;En el siguiente &lt;a href="https://blog.dacadev.com/programacion/estructura-datos-y-algoritmos/02-big-o-notation-y-algoritmos-de-ordenamiento"



 


&gt;&lt;strong&gt;post&lt;/strong&gt;&lt;/a&gt;, aprenderemos la forma matemática formal en la que los desarrolladores expresamos estas diferencias de eficiencia: la &lt;strong&gt;Notación Big O&lt;/strong&gt;, y cómo usarla para analizar nuestros primeros algoritmos de ordenamiento. ¡No te lo pierdas! 🚀&lt;/p&gt;</content:encoded></item><item><title>Agentes IA: ¿Qué es un Agente de Inteligencia Artificial?</title><link>https://blog.dacadev.com/generative-ai/agents/que-es-un-agente-ia/</link><pubDate>Fri, 15 May 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/generative-ai/agents/que-es-un-agente-ia/</guid><dc:creator>Dacadev</dc:creator><category>IA generativa</category><description>Descubre qué es un agente de inteligencia artificial, cómo funciona un LLM como cerebro del agente, y los módulos clave: memoria, herramientas y planificación.</description><media:content url="https://blog.dacadev.com/images/generative-ai/agents/01-que-es-un-agente/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#definición-formal-de-un-agente"&gt;Definición formal de un Agente&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#el-agente-basado-en-llm"&gt;El Agente basado en LLM&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#large-language-models-llms"&gt;Large Language Models (LLMs)&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#tokenización"&gt;Tokenización&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#autoregresión"&gt;Autoregresión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#llms-con-razonamiento"&gt;LLMs con Razonamiento&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#ejemplo-de-razonamiento"&gt;Ejemplo de razonamiento&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#aumentando-las-capacidades-del-llm"&gt;Aumentando las capacidades del LLM&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#memoria"&gt;Memoria&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#herramientas-tools"&gt;Herramientas (Tools)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#planificación-y-reflexión"&gt;Planificación y Reflexión&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#descomposición-de-tareas"&gt;Descomposición de tareas&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#ejecución-iterativa-con-razonamiento"&gt;Ejecución iterativa con razonamiento&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#reflexión"&gt;Reflexión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;En el mundo de la Inteligencia Artificial, los términos aparecen y se mezclan con una velocidad que a veces marea. Uno de los conceptos más poderosos —y más incomprendidos— es el de &lt;strong&gt;Agente de IA&lt;/strong&gt;. Seguro has escuchado el término, pero ¿qué significa realmente? ¿Qué hace que un sistema deje de ser un simple chatbot y se convierta en un agente capaz de percibir, razonar y actuar sobre su entorno?&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;En este artículo aprenderás qué es un agente de IA desde su definición formal, cómo un LLM actúa como su &amp;ldquo;cerebro&amp;rdquo;, y los módulos fundamentales que lo potencian: memoria, herramientas y planificación. 🚀&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="definición-formal-de-un-agente"&gt;Definición formal de un Agente&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;An agent is anything that can be viewed as perceiving its environment through sensors and acting upon that environment through actuators.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Russell &amp;amp; Norvig, AI: A Modern Approach&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Podemos descomponer esta definición en los componentes fundamentales que están en el corazón de todo agente:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Environment (Entorno)&lt;/strong&gt;: El mundo con el que el agente interactúa&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sensors (Sensores)&lt;/strong&gt;: Componentes que el agente usa para observar su entorno&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Actuators (Actuadores)&lt;/strong&gt;: Herramientas que el agente usa para actuar sobre el entorno&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Effector (Efector)&lt;/strong&gt;: El &amp;ldquo;cerebro&amp;rdquo; o las reglas que deciden cómo pasar de observaciones a acciones&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 E[🌍 Entorno] --&amp;gt;|percibe| S[📡 Sensores]
 S --&amp;gt;|observaciones| EF[🧠 Efector]
 EF --&amp;gt;|decisiones| A[🔧 Actuadores]
 A --&amp;gt;|actúa sobre| E
&lt;/pre&gt;

&lt;p&gt;Imagina un robot aspiradora: sus sensores detectan obstáculos y suciedad (entorno), su &amp;ldquo;cerebro&amp;rdquo; decide qué dirección tomar (efector), y sus motores y cepillos ejecutan la acción (actuadores). Un agente de IA funciona con la misma lógica, pero en un entorno digital.&lt;/p&gt;
&lt;h2 id="el-agente-basado-en-llm"&gt;El Agente basado en LLM&lt;/h2&gt;
&lt;p&gt;En la práctica, el &lt;strong&gt;Efector&lt;/strong&gt; o cerebro del agente tiende a ser un LLM con capacidad de razonamiento. A través de módulos adicionales —memoria, herramientas y planificación— este LLM es capaz de interactuar con su entorno.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Los &lt;strong&gt;Actuadores&lt;/strong&gt; son las herramientas del LLM (APIs, funciones, búsquedas)&lt;/li&gt;
&lt;li&gt;Los &lt;strong&gt;Sensores&lt;/strong&gt; son las capacidades multimodales del LLM (texto, imágenes, audio)&lt;/li&gt;
&lt;li&gt;El &lt;strong&gt;Usuario&lt;/strong&gt; forma parte del entorno e influye directamente en cómo se inicia el agente&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 U[👤 Usuario] --&amp;gt;|prompt| LLM[🧠 LLM - Cerebro del Agente]
 LLM --&amp;gt;|usa| T[🔧 Herramientas / Tools]
 LLM --&amp;gt;|consulta| M[💾 Memoria]
 LLM --&amp;gt;|genera| P[📋 Plan]
 T --&amp;gt;|resultados| LLM
 M --&amp;gt;|contexto| LLM
 P --&amp;gt;|siguiente paso| LLM
 LLM --&amp;gt;|respuesta| U
 T --&amp;gt;|modifica| ENV[🌍 Entorno Digital]
 ENV --&amp;gt;|datos| LLM
&lt;/pre&gt;

&lt;p&gt;Sin ninguna interacción del usuario, el LLM no tomará ninguna acción. El agente está fuertemente influenciado por cómo el usuario inicia la conversación.&lt;/p&gt;
&lt;h2 id="large-language-models-llms"&gt;Large Language Models (LLMs)&lt;/h2&gt;
&lt;p&gt;El LLM es considerado el &amp;ldquo;cerebro&amp;rdquo; del agente. Tradicionalmente, un LLM es un modelo que no hace más que &lt;strong&gt;predecir la siguiente palabra&lt;/strong&gt; basándose en un texto de entrada.&lt;/p&gt;
&lt;h3 id="tokenización"&gt;Tokenización&lt;/h3&gt;
&lt;p&gt;El LLM primero descompone la consulta de entrada en &lt;strong&gt;tokens&lt;/strong&gt;, que son sub-componentes de palabras que permiten al modelo generalizar a palabras que no ha visto antes. El modelo procesa estos tokens y hace una predicción sobre cuál podría ser el siguiente.&lt;/p&gt;




 
 
 
 &lt;div class="flex justify-center"&gt;
 &lt;img
 src="https://blog.dacadev.com/images/generative-ai/agents/01-que-es-un-agente/tokenizacion_hu_ecaeedb330f63e63.webp"
 alt="Imagen guia del contenido de la página"/&gt;
 &lt;/div&gt;
 
 
 


&lt;h3 id="autoregresión"&gt;Autoregresión&lt;/h3&gt;
&lt;p&gt;El LLM predice el siguiente token, usa ese token predicho para actualizar su entrada, y luego continúa las predicciones. Al hacer esto de forma iterativa —lo que se llama &lt;strong&gt;autoregresión&lt;/strong&gt;— puede crear respuestas completas a la consulta del usuario.&lt;/p&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 participant Input as Texto de entrada
 participant LLM as LLM
 participant Output as Texto generado

 Input-&amp;gt;&amp;gt;LLM: &amp;#34;El gato está&amp;#34;
 LLM-&amp;gt;&amp;gt;Output: &amp;#34;sentado&amp;#34;
 Note over Input,Output: Se agrega al input
 Input-&amp;gt;&amp;gt;LLM: &amp;#34;El gato está sentado&amp;#34;
 LLM-&amp;gt;&amp;gt;Output: &amp;#34;en&amp;#34;
 Note over Input,Output: Se agrega al input
 Input-&amp;gt;&amp;gt;LLM: &amp;#34;El gato está sentado en&amp;#34;
 LLM-&amp;gt;&amp;gt;Output: &amp;#34;la silla&amp;#34;
 Note over Output: Respuesta completa generada
&lt;/pre&gt;

&lt;p&gt;Cada predicción se alimenta de las anteriores, construyendo la respuesta palabra por palabra.&lt;/p&gt;
&lt;h2 id="llms-con-razonamiento"&gt;LLMs con Razonamiento&lt;/h2&gt;
&lt;p&gt;El campo de los agentes de IA descubrió que las capacidades de los LLMs aumentarían sustancialmente si pudieran &lt;strong&gt;razonar&lt;/strong&gt;. En lugar de que el modelo &amp;ldquo;piense&amp;rdquo; en silencio (a través de sus parámetros internos), ahora se entrenan para &amp;ldquo;pensar en voz alta&amp;rdquo; generando &lt;strong&gt;trazas de razonamiento&lt;/strong&gt; antes de derivar la respuesta.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 Q[📝 Consulta del usuario] --&amp;gt; T[💭 Pensamientos / Razonamiento]
 T --&amp;gt; R[✅ Respuesta final]
&lt;/pre&gt;

&lt;p&gt;La idea principal es que al escribir sus pensamientos primero mediante su comportamiento autoregresivo, el LLM puede dedicar cómputo adicional a estructurar su razonamiento antes de generar la respuesta. Como los humanos, al estructurar sus pensamientos, las consultas complejas que requieren razonamiento multi-paso son más fáciles de resolver.&lt;/p&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;En la práctica, estos &amp;ldquo;pensamientos&amp;rdquo; están ocultos para el usuario. La respuesta que ves generalmente representa un resumen del razonamiento interno del modelo.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id="ejemplo-de-razonamiento"&gt;Ejemplo de razonamiento&lt;/h3&gt;
&lt;p&gt;Veamos cómo un LLM con razonamiento aborda un problema complejo:&lt;/p&gt;




 
 
 
 &lt;div class="flex justify-center"&gt;
 &lt;img
 src="https://blog.dacadev.com/images/generative-ai/agents/01-que-es-un-agente/reasoning-example_hu_600adf9fb2790942.webp"
 alt="Imagen guia del contenido de la página"/&gt;
 &lt;/div&gt;
 
 
 


&lt;p&gt;El modelo genera una cadena de pensamientos internos, evalúa opciones y finalmente produce una respuesta bien fundamentada.&lt;/p&gt;
&lt;h2 id="aumentando-las-capacidades-del-llm"&gt;Aumentando las capacidades del LLM&lt;/h2&gt;
&lt;p&gt;Aunque los LLMs con razonamiento son vitales para los agentes de IA, siguen siendo incompletos. Como entidades estáticas de texto-a-texto, los LLMs no tienen control sobre su entorno, ni recuerdan sus interacciones, ni aprenden de ellas.&lt;/p&gt;
&lt;p&gt;Para convertir un LLM en un verdadero agente, necesitamos proveerlo de tres módulos fundamentales:&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 LLM[🧠 LLM con Razonamiento]
 MEM[💾 Memoria]
 TOOLS[🔧 Herramientas]
 PLAN[📋 Planificación y Reflexión]

 MEM --&amp;gt; LLM
 TOOLS --&amp;gt; LLM
 PLAN --&amp;gt; LLM

 LLM --&amp;gt; AGENT[🤖 Agente de IA]
&lt;/pre&gt;

&lt;h3 id="memoria"&gt;Memoria&lt;/h3&gt;
&lt;p&gt;Sin memoria, los LLMs operan en conversaciones de &lt;strong&gt;&amp;ldquo;single-turn&amp;rdquo;&lt;/strong&gt;: una sola pregunta y una sola respuesta. La información no persiste entre llamadas.&lt;/p&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 participant U as Usuario
 participant L as LLM

 U-&amp;gt;&amp;gt;L: ¿Cuál es la capital de Francia?
 L-&amp;gt;&amp;gt;U: París
 Note over U,L: ❌ Sin contexto previo
 U-&amp;gt;&amp;gt;L: ¿Y su población?
 L-&amp;gt;&amp;gt;U: ¿De qué ciudad hablas?
 Note over L: No recuerda la conversación anterior
&lt;/pre&gt;

&lt;p&gt;Afortunadamente, hay muchas formas de agregar módulos de memoria. La forma más común es simplemente añadir la conversación previa al prompt actual:&lt;/p&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 participant U as Usuario
 participant M as Memoria
 participant L as LLM

 U-&amp;gt;&amp;gt;L: ¿Cuál es la capital de Francia?
 L-&amp;gt;&amp;gt;U: París
 L-&amp;gt;&amp;gt;M: Guardar contexto
 U-&amp;gt;&amp;gt;L: ¿Y su población?
 M-&amp;gt;&amp;gt;L: Contexto: hablamos de París
 L-&amp;gt;&amp;gt;U: París tiene ~2.1 millones de habitantes
 Note over L: ✅ Recuerda el contexto
&lt;/pre&gt;





 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Los módulos de memoria pueden ser complejos. Si recibimos demasiada información, se vuelve difícil de procesar, lo que puede llevar a malas decisiones. Esto se llama &lt;strong&gt;sobrecarga de información&lt;/strong&gt; y es un problema real incluso para los LLMs. Se necesita un balance entre la cantidad y calidad de la información en el prompt — esto es lo que se conoce como &lt;strong&gt;context engineering&lt;/strong&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Los sistemas de memoria comparten similitudes con nuestros sistemas de memoria humana:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Memoria a corto plazo&lt;/strong&gt;: La conversación actual, las últimas interacciones&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memoria a largo plazo&lt;/strong&gt;: Hechos persistentes, preferencias del usuario, conocimiento acumulado&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="herramientas-tools"&gt;Herramientas (Tools)&lt;/h3&gt;
&lt;p&gt;Con la memoria, los LLMs recuerdan sus conversaciones previas, pero aún no son capaces de &lt;strong&gt;interactuar con su entorno&lt;/strong&gt;. Los LLMs pueden interactuar con su entorno digital a través de herramientas externas que amplían sus capacidades: calculadoras, motores de búsqueda, APIs, shells de comandos, y más.&lt;/p&gt;
&lt;p&gt;Sin embargo, los LLMs &lt;strong&gt;no son capaces de usar herramientas por sí mismos&lt;/strong&gt;. Fundamentalmente, un LLM es una función de texto-entrada/texto-salida. Solo puede &lt;em&gt;describir o expresar la intención&lt;/em&gt; de tomar una acción.&lt;/p&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 participant U as Usuario
 participant L as LLM
 participant R as Runtime / Orquestador
 participant T as Herramienta

 U-&amp;gt;&amp;gt;L: ¿Cuánto es 847 × 392?
 L-&amp;gt;&amp;gt;R: {&amp;#34;tool&amp;#34;: &amp;#34;calculator&amp;#34;, &amp;#34;params&amp;#34;: {&amp;#34;expr&amp;#34;: &amp;#34;847 * 392&amp;#34;}}
 Note over L,R: El LLM expresa INTENCIÓN
 R-&amp;gt;&amp;gt;T: Ejecutar cálculo
 T-&amp;gt;&amp;gt;R: 331,824
 R-&amp;gt;&amp;gt;L: Resultado: 331,824
 L-&amp;gt;&amp;gt;U: El resultado es 331,824
&lt;/pre&gt;





 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;El LLM puede expresar la intención de usar una herramienta, pero depende de nosotros convertir esa intención en una llamada real. Necesitamos escribir software que interprete el output del LLM (generalmente JSON) para elegir la herramienta correcta y completar sus parámetros.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Las herramientas varían en complejidad:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Simples&lt;/strong&gt;: Calculadoras, conversor de unidades&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Intermedias&lt;/strong&gt;: Búsqueda web, consultas a bases de datos&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Complejas&lt;/strong&gt;: Acceso a terminal, entornos de código, APIs de GitHub&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="planificación-y-reflexión"&gt;Planificación y Reflexión&lt;/h3&gt;
&lt;p&gt;El ingrediente final para ir de un LLM &amp;ldquo;regular&amp;rdquo; a un Agente de IA es su capacidad de &lt;strong&gt;planificar y reflexionar&lt;/strong&gt;. Estas capacidades son fundamentales, ya que el agente necesita decidir qué pasos tomar, cómo tomarlos y cuándo.&lt;/p&gt;
&lt;h4 id="descomposición-de-tareas"&gt;Descomposición de tareas&lt;/h4&gt;
&lt;p&gt;Aquí es donde entra la planificación: descomponer una tarea grande en pasos más pequeños y ejecutables. Esto se conoce como &lt;strong&gt;task decomposition&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 Q[📝 Query: Investiga papers recientes sobre RAG] --&amp;gt; P[📋 Plan]
 P --&amp;gt; T1[1. Buscar en Google Scholar]
 P --&amp;gt; T2[2. Buscar en ArXiv]
 P --&amp;gt; T3[3. Filtrar por fecha 2024-2025]
 P --&amp;gt; T4[4. Leer abstracts relevantes]
 P --&amp;gt; T5[5. Generar resumen comparativo]

 T1 --&amp;gt; E[⚡ Ejecución secuencial]
 T2 --&amp;gt; E
 T3 --&amp;gt; E
 T4 --&amp;gt; E
 T5 --&amp;gt; E
&lt;/pre&gt;

&lt;h4 id="ejecución-iterativa-con-razonamiento"&gt;Ejecución iterativa con razonamiento&lt;/h4&gt;
&lt;p&gt;Al referirse continuamente a su plan, el LLM ejecuta cada tarea una por una. Hacerlas todas a la vez rara vez es eficiente, ya que cada tarea puede influir en otra. Después de completar una tarea específica, el LLM razona sobre qué pasos tomar a continuación.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 START[🎯 Objetivo] --&amp;gt; PLAN[📋 Crear Plan]
 PLAN --&amp;gt; EXEC[⚡ Ejecutar Tarea]
 EXEC --&amp;gt; REASON[🤔 Razonar sobre resultado]
 REASON --&amp;gt;|siguiente tarea| EXEC
 REASON --&amp;gt;|plan completo| DONE[✅ Resultado Final]
 REASON --&amp;gt;|ajustar plan| REFLECT[🔄 Reflexionar]
 REFLECT --&amp;gt;|plan mejorado| PLAN
&lt;/pre&gt;

&lt;h4 id="reflexión"&gt;Reflexión&lt;/h4&gt;
&lt;p&gt;Crear un plan no es suficiente. El LLM puede descubrir a mitad del camino que algunos pasos no son apropiados. Por ejemplo, podría descubrir que Google y ArXiv son insuficientes y decidir agregar Semantic Scholar y PubMed como recursos adicionales.&lt;/p&gt;
&lt;p&gt;Este comportamiento &lt;strong&gt;reflexivo&lt;/strong&gt; hace que los agentes parezcan humanos: intentan descubrir sus fallos y hacer intentos por corregirlos. Al reflexionar sobre comportamiento pasado, el plan inicial puede mejorarse continuamente.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;La planificación y reflexión crean un &lt;strong&gt;ciclo iterativo&lt;/strong&gt;: planificar tareas → ejecutar acciones → reflexionar sobre el resultado → ajustar el plan. Este ciclo es lo que diferencia a un verdadero agente de un simple modelo que responde preguntas. 🚀&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;Un agente de IA no es simplemente un LLM que responde preguntas. Es un sistema compuesto por:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Un LLM con razonamiento&lt;/strong&gt; como cerebro central&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memoria&lt;/strong&gt; para mantener contexto entre interacciones&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Herramientas&lt;/strong&gt; para interactuar con el entorno digital&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Planificación y reflexión&lt;/strong&gt; para abordar tareas complejas de forma iterativa&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 subgraph AGENT[🤖 Agente de IA]
 direction TB
 BRAIN[🧠 LLM con Razonamiento]
 MEM[💾 Memoria&amp;lt;br/&amp;gt;Corto y largo plazo]
 TOOLS[🔧 Herramientas&amp;lt;br/&amp;gt;APIs, búsqueda, código]
 PLAN[📋 Planificación&amp;lt;br/&amp;gt;Descomposición + Reflexión]

 MEM &amp;lt;--&amp;gt; BRAIN
 TOOLS &amp;lt;--&amp;gt; BRAIN
 PLAN &amp;lt;--&amp;gt; BRAIN
 end

 USER[👤 Usuario] &amp;lt;--&amp;gt;|interacción| AGENT
 AGENT &amp;lt;--&amp;gt;|percibe y actúa| ENV[🌍 Entorno]
&lt;/pre&gt;

&lt;p&gt;La próxima vez que interactúes con un asistente de IA que busca información, ejecuta código y ajusta su enfoque basándose en los resultados, estarás interactuando con un agente. Y ahora entiendes la maquinaria que lo hace posible.&lt;/p&gt;</content:encoded></item><item><title>asyncio: Cómo Funcionan los Procesos, Hilos y el Event Loop</title><link>https://blog.dacadev.com/python/asyncio/procesos-hilos-event-loop/</link><pubDate>Mon, 11 May 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/python/asyncio/procesos-hilos-event-loop/</guid><dc:creator>Dacadev</dc:creator><category>python</category><description>Entiende qué son los procesos e hilos en Python, cómo el GIL afecta la concurrencia, y cómo asyncio logra concurrencia con un solo hilo gracias al event loop.</description><media:content url="https://blog.dacadev.com/images/python/asyncio/processes-threads/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#procesos-e-hilos"&gt;Procesos e Hilos&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#qué-es-un-proceso"&gt;¿Qué es un proceso?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#qué-es-un-hilo-thread"&gt;¿Qué es un hilo (thread)?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#verificándolo-en-python"&gt;Verificándolo en Python&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#el-global-interpreter-lock-gil"&gt;El Global Interpreter Lock (GIL)&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#el-gil-se-libera-alguna-vez"&gt;¿El GIL se libera alguna vez?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#asyncio-y-el-gil"&gt;&lt;code&gt;asyncio&lt;/code&gt; y el GIL&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#concurrencia-de-un-solo-hilo"&gt;Concurrencia de Un Solo Hilo&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#cómo-funciona-el-event-loop"&gt;Cómo Funciona el Event Loop&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#en-conclusión"&gt;En conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#referencias"&gt;Referencias&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;En el &lt;a href="https://blog.dacadev.com/python/asyncio/fundamentos-asyncio"



 


&gt;artículo anterior&lt;/a&gt; construimos un modelo mental sobre concurrencia, paralelismo y los tipos de multitarea. Ahora vamos a bajar un nivel: entender qué son los procesos y los hilos, por qué el GIL de Python cambia las reglas del juego, y cómo &lt;code&gt;asyncio&lt;/code&gt; logra concurrencia con un solo hilo gracias al event loop.&lt;/p&gt;
&lt;h2 id="procesos-e-hilos"&gt;Procesos e Hilos&lt;/h2&gt;
&lt;h3 id="qué-es-un-proceso"&gt;¿Qué es un proceso?&lt;/h3&gt;
&lt;p&gt;Un &lt;strong&gt;proceso&lt;/strong&gt; es una instancia de una aplicación en ejecución. Cada proceso tiene su propio espacio de memoria aislado — ningún otro proceso puede acceder a él directamente — y se ejecuta en un CPU o núcleo del sistema.&lt;/p&gt;
&lt;h3 id="qué-es-un-hilo-thread"&gt;¿Qué es un hilo (thread)?&lt;/h3&gt;
&lt;p&gt;Un &lt;strong&gt;hilo&lt;/strong&gt; es una unidad de ejecución más ligera que vive &lt;em&gt;dentro&lt;/em&gt; de un proceso. A diferencia de los procesos, los hilos no tienen su propia memoria: comparten el espacio de memoria del proceso que los creó.&lt;/p&gt;
&lt;p&gt;Todo proceso tiene al menos un hilo asociado, conocido como el &lt;strong&gt;hilo principal&lt;/strong&gt; (&lt;em&gt;main thread&lt;/em&gt;). Además, un proceso puede crear hilos adicionales, comúnmente llamados &lt;strong&gt;hilos de trabajo&lt;/strong&gt; (&lt;em&gt;worker threads&lt;/em&gt;) o &lt;strong&gt;hilos en segundo plano&lt;/strong&gt; (&lt;em&gt;background threads&lt;/em&gt;).&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TB
 subgraph P1[&amp;#34;Proceso (PID: 1234)&amp;#34;]
 direction TB
 M1[&amp;#34;Memoria del proceso&amp;#34;]
 MT[&amp;#34;Hilo principal\n(main thread)&amp;#34;]
 W1[&amp;#34;Worker thread 1&amp;#34;]
 W2[&amp;#34;Worker thread 2&amp;#34;]
 M1 &amp;lt;--&amp;gt; MT
 M1 &amp;lt;--&amp;gt; W1
 M1 &amp;lt;--&amp;gt; W2
 end

 style P1 fill:transparent,stroke:#64748b
 style M1 fill:#3b82f6,stroke:#1e40af,color:#fff
 style MT fill:#10b981,stroke:#065f46,color:#fff
 style W1 fill:#f59e0b,stroke:#b45309,color:#fff
 style W2 fill:#f59e0b,stroke:#b45309,color:#fff
&lt;/pre&gt;





 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Todos los hilos dentro de un proceso comparten la misma memoria. Esto hace la comunicación entre hilos muy rápida, pero introduce el riesgo de &lt;strong&gt;condiciones de carrera&lt;/strong&gt; si no se maneja con cuidado.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id="verificándolo-en-python"&gt;Verificándolo en Python&lt;/h3&gt;
&lt;p&gt;Puedes inspeccionar el proceso e hilo actual con los módulos &lt;code&gt;os&lt;/code&gt; y &lt;code&gt;threading&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;threading&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;Proceso de Python con PID: &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;os&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;getpid&lt;/span&gt;()&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;total_threads&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;threading&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;active_count&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;thread_name&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;threading&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;current_thread&lt;/span&gt;()&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;Python está ejecutando &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;total_threads&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; hilo(s)&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;El hilo actual es: &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;thread_name&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Output esperado&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Proceso de Python con PID: &lt;span style="color:#d19a66"&gt;48672&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Python está ejecutando &lt;span style="color:#d19a66"&gt;1&lt;/span&gt; hilo&lt;span style="color:#56b6c2"&gt;(&lt;/span&gt;s&lt;span style="color:#56b6c2"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;El hilo actual es: MainThread
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Por defecto, tu programa Python corre en un solo hilo (&lt;em&gt;MainThread&lt;/em&gt;) dentro de un solo proceso.&lt;/p&gt;
&lt;h2 id="el-global-interpreter-lock-gil"&gt;El Global Interpreter Lock (GIL)&lt;/h2&gt;
&lt;p&gt;El &lt;strong&gt;GIL&lt;/strong&gt; (&lt;em&gt;Global Interpreter Lock&lt;/em&gt;) es uno de los temas más debatidos en la comunidad Python. En términos simples: el GIL impide que un proceso de Python ejecute más de una instrucción de bytecode a la vez, incluso si tienes múltiples hilos.&lt;/p&gt;
&lt;p&gt;Esto significa que aunque crees varios hilos con &lt;code&gt;threading&lt;/code&gt;, &lt;strong&gt;solo uno ejecuta código Python en cualquier instante&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 participant GIL
 participant T1 as Hilo 1
 participant T2 as Hilo 2

 GIL-&amp;gt;&amp;gt;T1: 🔓 GIL adquirido
 activate T1
 T1-&amp;gt;&amp;gt;T1: Ejecuta bytecode
 T1-&amp;gt;&amp;gt;GIL: 🔒 Libera GIL
 deactivate T1
 GIL-&amp;gt;&amp;gt;T2: 🔓 GIL adquirido
 activate T2
 T2-&amp;gt;&amp;gt;T2: Ejecuta bytecode
 T2-&amp;gt;&amp;gt;GIL: 🔒 Libera GIL
 deactivate T2
 GIL-&amp;gt;&amp;gt;T1: 🔓 GIL adquirido
 activate T1
 T1-&amp;gt;&amp;gt;T1: Ejecuta bytecode
 deactivate T1
&lt;/pre&gt;

&lt;h3 id="el-gil-se-libera-alguna-vez"&gt;¿El GIL se libera alguna vez?&lt;/h3&gt;
&lt;p&gt;Sí. El GIL &lt;strong&gt;se libera durante las operaciones de I/O&lt;/strong&gt;. Cuando un hilo hace una petición de red o una lectura de disco, libera el GIL, permitiendo que otro hilo tome el control y ejecute código Python mientras tanto.&lt;/p&gt;
&lt;p&gt;Esto es lo que hace que &lt;code&gt;threading&lt;/code&gt; sea útil para trabajo I/O-bound, pero ineficaz para trabajo CPU-bound.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 A[&amp;#34;Operación\nCPU-bound&amp;#34;] --&amp;gt;|&amp;#34;GIL retenido 🔒&amp;#34;| B[&amp;#34;Solo 1 hilo\nejecuta a la vez&amp;#34;]
 C[&amp;#34;Operación\nI/O-bound&amp;#34;] --&amp;gt;|&amp;#34;GIL liberado 🔓&amp;#34;| D[&amp;#34;Otros hilos pueden\nejecutar código&amp;#34;]

 style A fill:#ef4444,stroke:#991b1b,color:#fff
 style B fill:#ef4444,stroke:#991b1b,color:#fff
 style C fill:#10b981,stroke:#065f46,color:#fff
 style D fill:#10b981,stroke:#065f46,color:#fff
&lt;/pre&gt;

&lt;h3 id="asyncio-y-el-gil"&gt;&lt;code&gt;asyncio&lt;/code&gt; y el GIL&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;asyncio&lt;/code&gt; aprovecha exactamente este comportamiento: como las operaciones de I/O liberan el GIL, puede lograr concurrencia &lt;strong&gt;con un solo hilo&lt;/strong&gt;. En lugar de crear múltiples hilos, &lt;code&gt;asyncio&lt;/code&gt; crea objetos llamados &lt;strong&gt;coroutines&lt;/strong&gt; — que puedes pensar como hilos ultra-ligeros.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Mientras una coroutine espera por una operación de I/O, el event loop ejecuta otras coroutines que estén listas. El resultado: concurrencia sin los problemas de sincronización del multithreading.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="concurrencia-de-un-solo-hilo"&gt;Concurrencia de Un Solo Hilo&lt;/h2&gt;
&lt;p&gt;La concurrencia de un solo hilo no se basa en hacer dos cosas simultáneamente (eso sería paralelismo), sino en &lt;strong&gt;aprovechar los tiempos de espera&lt;/strong&gt; de las operaciones de I/O para ejecutar otras tareas. El mecanismo se apoya en tres pilares:&lt;/p&gt;



&lt;div class="tab" data-tab-group=""&gt;
 &lt;ul class="tab-nav" data-tab-nav&gt;
 
 &lt;li
 class="tab-nav-item active"
 data-tab="sockets-no-bloqueantes" tabindex="0"&gt;
 Sockets no bloqueantes
 &lt;/li&gt;
 
 &lt;li
 class="tab-nav-item "
 data-tab="delegaci%C3%B3n-al-so" tabindex="-1"&gt;
 Delegación al SO
 &lt;/li&gt;
 
 &lt;li
 class="tab-nav-item "
 data-tab="event-loop" tabindex="-1"&gt;
 Event Loop
 &lt;/li&gt;
 
 &lt;/ul&gt;
 &lt;div class="tab-content" data-tab-content&gt;
 
 &lt;div
 class="tab-content-panel active"
 data-tab-panel="sockets-no-bloqueantes"&gt;
 &lt;h4 id="1-sockets-no-bloqueantes"&gt;1. Sockets no bloqueantes&lt;/h4&gt;
&lt;p&gt;A diferencia de un socket estándar que detiene el programa hasta recibir una respuesta, un &lt;strong&gt;socket no bloqueante&lt;/strong&gt; permite enviar una petición y devolver el control al programa inmediatamente, sin esperar el resultado.&lt;/p&gt;

 &lt;/div&gt;
 
 &lt;div
 class="tab-content-panel "
 data-tab-panel="delegaci%C3%B3n-al-so"&gt;
 &lt;h4 id="2-delegación-al-sistema-operativo"&gt;2. Delegación al sistema operativo&lt;/h4&gt;
&lt;p&gt;Cuando el código llega a una operación de red o lectura de disco, Python le delega la espera al sistema operativo. El hilo de ejecución queda libre de inmediato.&lt;/p&gt;

 &lt;/div&gt;
 
 &lt;div
 class="tab-content-panel "
 data-tab-panel="event-loop"&gt;
 &lt;h4 id="3-el-event-loop-como-coordinador"&gt;3. El Event Loop como coordinador&lt;/h4&gt;
&lt;p&gt;Mientras el SO vigila los sockets, el hilo de Python sigue ejecutando otras tareas. Cuando el SO detecta que los datos llegaron, envía una notificación. El event loop recibe este aviso y &amp;ldquo;despierta&amp;rdquo; la tarea pausada para que procese la respuesta.&lt;/p&gt;

 &lt;/div&gt;
 
 &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;El siguiente diagrama de secuencia muestra cómo interactúan estos tres pilares:&lt;/p&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 participant MT as Main Thread
 participant EL as Event Loop
 participant OS as Sistema Operativo
 participant S1 as Socket 1
 participant S2 as Socket 2

 MT-&amp;gt;&amp;gt;EL: Envía tareas
 EL-&amp;gt;&amp;gt;EL: Ejecuta tarea 1 hasta I/O
 EL-&amp;gt;&amp;gt;OS: Registra Socket 1 para monitoreo
 OS-&amp;gt;&amp;gt;S1: Vigila socket
 EL-&amp;gt;&amp;gt;EL: Ejecuta tarea 2 hasta I/O
 EL-&amp;gt;&amp;gt;OS: Registra Socket 2 para monitoreo
 OS-&amp;gt;&amp;gt;S2: Vigila socket
 S1--&amp;gt;&amp;gt;OS: Datos listos ✅
 OS--&amp;gt;&amp;gt;EL: Notifica Socket 1
 EL-&amp;gt;&amp;gt;EL: Reanuda tarea 1
 S2--&amp;gt;&amp;gt;OS: Datos listos ✅
 OS--&amp;gt;&amp;gt;EL: Notifica Socket 2
 EL-&amp;gt;&amp;gt;EL: Reanuda tarea 2
&lt;/pre&gt;

&lt;h2 id="cómo-funciona-el-event-loop"&gt;Cómo Funciona el Event Loop&lt;/h2&gt;
&lt;p&gt;En su forma más básica, un event loop es simplemente un &lt;strong&gt;bucle infinito que procesa mensajes de una cola&lt;/strong&gt;, uno a la vez:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;collections&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;deque&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;messages&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;deque&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;while&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;True&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; &lt;span style="color:#e06c75"&gt;messages&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;message&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;messages&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;pop&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;process_message&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;message&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En &lt;code&gt;asyncio&lt;/code&gt;, el event loop mantiene una cola de &lt;strong&gt;tasks&lt;/strong&gt; (tareas) en lugar de mensajes simples. Cada task es un wrapper alrededor de una coroutine. Cuando una coroutine alcanza una operación de I/O, se pausa y le devuelve el control al event loop, que puede ejecutar otras tareas que no estén esperando I/O.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 A[&amp;#34;Event Loop inicia&amp;#34;] --&amp;gt; B[&amp;#34;¿Hay tareas en la cola?&amp;#34;]
 B --&amp;gt;|Sí| C[&amp;#34;Tomar siguiente tarea&amp;#34;]
 C --&amp;gt; D{&amp;#34;¿La tarea tiene\nI/O pendiente?&amp;#34;}
 D --&amp;gt;|No| E[&amp;#34;Ejecutar hasta\nel próximo await&amp;#34;]
 E --&amp;gt; F{&amp;#34;¿La tarea alcanzó\nuna operación I/O?&amp;#34;}
 F --&amp;gt;|Sí| G[&amp;#34;Pausar tarea y registrar\nsocket en el SO&amp;#34;]
 F --&amp;gt;|No| H[&amp;#34;Tarea completada ✅\nRemover de la cola&amp;#34;]
 G --&amp;gt; B
 H --&amp;gt; B
 D --&amp;gt;|Sí, datos listos| I[&amp;#34;Reanudar tarea&amp;#34;]
 I --&amp;gt; F
 D --&amp;gt;|Sí, esperando aún| B
 B --&amp;gt;|No| J[&amp;#34;Esperar notificaciones\ndel SO&amp;#34;]
 J --&amp;gt; B

 style A fill:#3b82f6,stroke:#1e40af,color:#fff
 style H fill:#10b981,stroke:#065f46,color:#fff
&lt;/pre&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Este ciclo se repite indefinidamente hasta que todas las tareas se completan o el programa se cierra explícitamente. Si una coroutine ejecuta trabajo CPU-bound sin ceder control con &lt;code&gt;await&lt;/code&gt;, &lt;strong&gt;bloqueará todo el event loop&lt;/strong&gt; y ninguna otra tarea podrá avanzar.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="en-conclusión"&gt;En conclusión&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Un &lt;strong&gt;proceso&lt;/strong&gt; tiene memoria aislada; un &lt;strong&gt;hilo&lt;/strong&gt; comparte memoria dentro de su proceso.&lt;/li&gt;
&lt;li&gt;El &lt;strong&gt;GIL&lt;/strong&gt; impide paralelismo real con hilos en Python, pero se libera durante operaciones de I/O.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;asyncio&lt;/code&gt; aprovecha esta liberación del GIL para lograr &lt;strong&gt;concurrencia en un solo hilo&lt;/strong&gt; mediante coroutines.&lt;/li&gt;
&lt;li&gt;El &lt;strong&gt;event loop&lt;/strong&gt; coordina las tareas: ejecuta coroutines hasta que alcanzan un &lt;code&gt;await&lt;/code&gt;, las pausa, y reanuda otras que ya tengan datos listos.&lt;/li&gt;
&lt;li&gt;Los &lt;strong&gt;sockets no bloqueantes&lt;/strong&gt; y la &lt;strong&gt;delegación al SO&lt;/strong&gt; son los mecanismos que permiten esta concurrencia sin crear múltiples hilos.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="referencias"&gt;Referencias&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/asyncio.html"




 target="_blank"
 


&gt;Python &lt;code&gt;asyncio&lt;/code&gt; — Documentación Oficial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/threading.html"




 target="_blank"
 


&gt;Python &lt;code&gt;threading&lt;/code&gt; — Documentación Oficial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/multiprocessing.html"




 target="_blank"
 


&gt;Python &lt;code&gt;multiprocessing&lt;/code&gt; — Documentación Oficial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://realpython.com/python-gil/"




 target="_blank"
 


&gt;Real Python — What Is the Python Global Interpreter Lock (GIL)?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://peps.python.org/pep-0703/"




 target="_blank"
 


&gt;PEP 703 — Making the Global Interpreter Lock Optional&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>asyncio: Los Fundamentos de la Programación Asíncrona en Python</title><link>https://blog.dacadev.com/python/asyncio/fundamentos-asyncio/</link><pubDate>Sun, 10 May 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/python/asyncio/fundamentos-asyncio/</guid><dc:creator>Dacadev</dc:creator><category>python</category><description>Aprende los fundamentos de asyncio en Python: diferencia entre concurrencia y paralelismo, operaciones CPU-bound vs I/O-bound, y cómo funciona la multitarea cooperativa.</description><media:content url="https://blog.dacadev.com/images/python/asyncio/fundamentals/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#qué-es-la-programación-asíncrona"&gt;¿Qué es la programación asíncrona?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#cpu-bound-vs-io-bound"&gt;CPU-bound vs. I/O-bound&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#operaciones-limitadas-por-es-io-bound"&gt;Operaciones limitadas por E/S (I/O-bound)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#operaciones-limitadas-por-cpu-cpu-bound"&gt;Operaciones limitadas por CPU (CPU-bound)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#ejemplo-práctico"&gt;Ejemplo práctico&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#concurrencia-vs-paralelismo"&gt;Concurrencia vs. Paralelismo&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#concurrencia-alternar-entre-tareas"&gt;Concurrencia: alternar entre tareas&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#paralelismo-ejecución-simultánea-real"&gt;Paralelismo: ejecución simultánea real&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#tipos-de-multitarea"&gt;Tipos de Multitarea&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#multitarea-preventiva-preemptive"&gt;Multitarea preventiva (Preemptive)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#multitarea-cooperativa-cooperative"&gt;Multitarea cooperativa (Cooperative)&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#comparación-rápida"&gt;Comparación rápida&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#dónde-encaja-asyncio"&gt;¿Dónde encaja &lt;code&gt;asyncio&lt;/code&gt;?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#en-conclusión"&gt;En conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#referencias"&gt;Referencias&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Si alguna vez construiste un scraper que recorre decenas de páginas, un microservicio que atiende cientos de peticiones o un bot que consume múltiples APIs, seguro sentiste la frustración de esperar. Una petición termina, la siguiente arranca, y tu programa queda ahí sin hacer nada útil.&lt;/p&gt;
&lt;p&gt;La librería &lt;code&gt;asyncio&lt;/code&gt; de Python fue diseñada para resolver exactamente este problema. En este artículo vamos a construir un modelo mental sólido sobre los conceptos clave: concurrencia, paralelismo, multitarea y la diferencia entre operaciones limitadas por CPU y por E/S.&lt;/p&gt;
&lt;h2 id="qué-es-la-programación-asíncrona"&gt;¿Qué es la programación asíncrona?&lt;/h2&gt;
&lt;p&gt;La &lt;strong&gt;programación asíncrona&lt;/strong&gt; es un modelo donde las tareas de larga duración se ejecutan en segundo plano, separadas del flujo principal de tu aplicación. En lugar de bloquear todo mientras esperas una respuesta de red o una lectura de archivo, el sistema queda libre para hacer otro trabajo. Cuando la tarea termina, tu código recibe una notificación y puede procesar el resultado.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;code&gt;asyncio&lt;/code&gt; — abreviación de &lt;strong&gt;asynchronous I/O&lt;/strong&gt; — es la librería estándar de Python que implementa este modelo. Fue introducida en &lt;a href="https://docs.python.org/3/library/asyncio.html"




 target="_blank"
 


&gt;Python 3.4&lt;/a&gt; y hoy es la base de frameworks modernos como &lt;a href="https://fastapi.tiangolo.com/"




 target="_blank"
 


&gt;FastAPI&lt;/a&gt;, &lt;a href="https://docs.aiohttp.org/"




 target="_blank"
 


&gt;aiohttp&lt;/a&gt; y &lt;a href="https://www.starlette.io/"




 target="_blank"
 


&gt;Starlette&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="cpu-bound-vs-io-bound"&gt;CPU-bound vs. I/O-bound&lt;/h2&gt;
&lt;p&gt;Antes de avanzar, necesitas entender una distinción fundamental: &lt;strong&gt;¿en qué está gastando tiempo tu código?&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="operaciones-limitadas-por-es-io-bound"&gt;Operaciones limitadas por E/S (I/O-bound)&lt;/h3&gt;
&lt;p&gt;Tu programa pasa la mayor parte del tiempo &lt;strong&gt;esperando un sistema externo&lt;/strong&gt;: la red, el disco, una base de datos. La CPU está prácticamente ociosa. Ejemplos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hacer peticiones HTTP.&lt;/li&gt;
&lt;li&gt;Leer o escribir archivos en disco.&lt;/li&gt;
&lt;li&gt;Consultar una base de datos.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="operaciones-limitadas-por-cpu-cpu-bound"&gt;Operaciones limitadas por CPU (CPU-bound)&lt;/h3&gt;
&lt;p&gt;El &lt;strong&gt;procesador&lt;/strong&gt; es el cuello de botella. La CPU está activamente calculando, sin esperas externas. Ejemplos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Calcular dígitos de pi.&lt;/li&gt;
&lt;li&gt;Aplicar lógica de negocio sobre estructuras de datos grandes.&lt;/li&gt;
&lt;li&gt;Procesamiento de imágenes o entrenamiento de modelos.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ejemplo-práctico"&gt;Ejemplo práctico&lt;/h3&gt;
&lt;p&gt;Considera este fragmento de código:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;requests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;response&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;requests&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;get&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;https://www.example.com&amp;#39;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# 1 - I/O-bound&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;items&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;response&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;headers&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;items&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;headers&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;key&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;: &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;header&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;&lt;/span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; &lt;span style="color:#e06c75"&gt;key&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;header&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;in&lt;/span&gt; &lt;span style="color:#e06c75"&gt;items&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;# 2 - CPU-bound&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;formatted_headers&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#98c379"&gt;\n&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;join&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;headers&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# 3 - CPU-bound&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;with&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;open&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#39;headers.txt&amp;#39;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;) &lt;span style="color:#c678dd"&gt;as&lt;/span&gt; &lt;span style="color:#e06c75"&gt;file&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;file&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;write&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;formatted_headers&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# 4 - I/O-bound&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El siguiente diagrama muestra el flujo de ejecución y clasifica cada paso:&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
 A[&amp;#34;1. requests.get()&amp;#34;] --&amp;gt;|respuesta| B[&amp;#34;2. List comprehension&amp;#34;]
 B --&amp;gt; C[&amp;#34;3. join() headers&amp;#34;]
 C --&amp;gt; D[&amp;#34;4. file.write()&amp;#34;]

 style A fill:#3b82f6,stroke:#1e40af,color:#fff
 style B fill:#f59e0b,stroke:#b45309,color:#fff
 style C fill:#f59e0b,stroke:#b45309,color:#fff
 style D fill:#3b82f6,stroke:#1e40af,color:#fff
&lt;/pre&gt;

&lt;blockquote&gt;
&lt;p&gt;🔵 &lt;strong&gt;Azul = I/O-bound&lt;/strong&gt; (esperando red o disco) · 🟡 &lt;strong&gt;Amarillo = CPU-bound&lt;/strong&gt; (procesando en memoria)&lt;/p&gt;
&lt;/blockquote&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;code&gt;asyncio&lt;/code&gt; brilla con cargas &lt;strong&gt;I/O-bound&lt;/strong&gt;. Si tu cuello de botella es la CPU, necesitarás &lt;code&gt;multiprocessing&lt;/code&gt; o &lt;a href="https://docs.python.org/3/library/concurrent.futures.html"




 target="_blank"
 


&gt;concurrent.futures&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="concurrencia-vs-paralelismo"&gt;Concurrencia vs. Paralelismo&lt;/h2&gt;
&lt;p&gt;Estos dos términos se confunden constantemente, pero describen cosas distintas.&lt;/p&gt;
&lt;h3 id="concurrencia-alternar-entre-tareas"&gt;Concurrencia: alternar entre tareas&lt;/h3&gt;
&lt;p&gt;Concurrencia significa &lt;strong&gt;gestionar múltiples tareas en períodos de tiempo superpuestos&lt;/strong&gt;, sin necesidad de ejecutarlas en el mismo instante. Piensa en un chef preparando dos platos: pica verduras para el plato A, lo mete al horno y empieza a trabajar en el plato B mientras el A se cocina. Solo hace una cosa a la vez, pero ambos platos avanzan.&lt;/p&gt;
&lt;p&gt;En un sistema concurrente, una sola CPU alterna entre tareas. Mientras la tarea #1 espera por E/S, la CPU toma la tarea #2.&lt;/p&gt;
&lt;pre class="mermaid"&gt;gantt
 title Concurrencia — Una sola CPU alternando entre tareas
 dateFormat X
 axisFormat %s

 section CPU
 App #1 :a1, 0, 2
 App #2 :a2, 2, 4
 App #1 :a3, 4, 6
 App #2 :a4, 6, 8
 App #1 :a5, 8, 10
&lt;/pre&gt;

&lt;h3 id="paralelismo-ejecución-simultánea-real"&gt;Paralelismo: ejecución simultánea real&lt;/h3&gt;
&lt;p&gt;Paralelismo significa &lt;strong&gt;ejecutar múltiples tareas al mismo tiempo&lt;/strong&gt;, lo cual requiere múltiples CPUs o núcleos.&lt;/p&gt;
&lt;pre class="mermaid"&gt;gantt
 title Paralelismo — Múltiples CPUs ejecutando simultáneamente
 dateFormat X
 axisFormat %s

 section CPU 1
 App #1 :a1, 0, 10

 section CPU 2
 App #2 :b1, 0, 10
&lt;/pre&gt;

&lt;p&gt;En palabras de Rob Pike (co-creador de Go): &lt;em&gt;&amp;ldquo;La concurrencia se trata de lidiar con muchas cosas a la vez. El paralelismo se trata de hacer muchas cosas a la vez.&amp;rdquo;&lt;/em&gt;&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;La concurrencia es un &lt;strong&gt;patrón de diseño&lt;/strong&gt;; el paralelismo es un &lt;strong&gt;modelo de ejecución&lt;/strong&gt;. &lt;code&gt;asyncio&lt;/code&gt; logra concurrencia en un solo hilo, sin paralelismo.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="tipos-de-multitarea"&gt;Tipos de Multitarea&lt;/h2&gt;
&lt;p&gt;Existen dos enfoques principales para la multitarea, y entender la diferencia es clave para comprender dónde encaja &lt;code&gt;asyncio&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="multitarea-preventiva-preemptive"&gt;Multitarea preventiva (Preemptive)&lt;/h3&gt;
&lt;p&gt;El &lt;strong&gt;sistema operativo&lt;/strong&gt; decide cuándo cambiar entre tareas mediante un mecanismo llamado &lt;strong&gt;time slicing&lt;/strong&gt;: divide el tiempo de CPU en intervalos pequeños y rota entre las tareas activas. Cuando el SO fuerza un cambio, se dice que está haciendo &lt;em&gt;preemption&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;En Python, este es el modelo que usan los módulos &lt;code&gt;threading&lt;/code&gt; (hilos) y &lt;code&gt;multiprocessing&lt;/code&gt; (procesos). La ventaja es que no tienes que pensar en cuándo ceder el control. La desventaja: los cambios pueden ocurrir en cualquier momento, lo que introduce &lt;strong&gt;condiciones de carrera&lt;/strong&gt; y la necesidad de &lt;strong&gt;locks&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="multitarea-cooperativa-cooperative"&gt;Multitarea cooperativa (Cooperative)&lt;/h3&gt;
&lt;p&gt;Las &lt;strong&gt;propias tareas&lt;/strong&gt; deciden cuándo ceder el control. Cada tarea señala explícitamente: &lt;em&gt;&amp;ldquo;Me pauso aquí, ejecuta otras tareas.&amp;rdquo;&lt;/em&gt; No hay intervención del SO.&lt;/p&gt;
&lt;p&gt;Este es exactamente el modelo de &lt;code&gt;asyncio&lt;/code&gt;. En Python, la palabra clave &lt;code&gt;await&lt;/code&gt; es esa señal explícita:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;obtener_datos&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Obteniendo datos...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;sleep&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;2&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# 👈 &amp;#34;Me pauso aquí, ejecuta otras tareas&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Datos obtenidos!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;procesar_datos&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Procesando datos...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;sleep&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# 👈 Misma señal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Datos procesados!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;async&lt;/span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;main&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;await&lt;/span&gt; &lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;gather&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;obtener_datos&lt;/span&gt;(), &lt;span style="color:#e06c75"&gt;procesar_datos&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;asyncio&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;run&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;main&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La ventaja es la &lt;strong&gt;predictibilidad&lt;/strong&gt;: tú controlas exactamente dónde ocurren los cambios. El riesgo: si una tarea olvida hacer &lt;code&gt;await&lt;/code&gt; o ejecuta una operación CPU-bound larga sin ceder control, bloquea todo el event loop.&lt;/p&gt;
&lt;p&gt;El siguiente diagrama de secuencia ilustra cómo el event loop coordina las tareas cooperativamente:&lt;/p&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 participant EL as Event Loop
 participant T1 as obtener_datos()
 participant T2 as procesar_datos()

 EL-&amp;gt;&amp;gt;T1: Ejecutar
 T1-&amp;gt;&amp;gt;EL: await sleep(2) — cede control
 EL-&amp;gt;&amp;gt;T2: Ejecutar
 T2-&amp;gt;&amp;gt;EL: await sleep(1) — cede control
 EL-&amp;gt;&amp;gt;T2: sleep completado — reanudar
 T2-&amp;gt;&amp;gt;EL: Finalizada ✅
 EL-&amp;gt;&amp;gt;T1: sleep completado — reanudar
 T1-&amp;gt;&amp;gt;EL: Finalizada ✅
&lt;/pre&gt;

&lt;h3 id="comparación-rápida"&gt;Comparación rápida&lt;/h3&gt;



&lt;div class="tab" data-tab-group=""&gt;
 &lt;ul class="tab-nav" data-tab-nav&gt;
 
 &lt;li
 class="tab-nav-item active"
 data-tab="preventiva" tabindex="0"&gt;
 Preventiva
 &lt;/li&gt;
 
 &lt;li
 class="tab-nav-item "
 data-tab="cooperativa" tabindex="-1"&gt;
 Cooperativa
 &lt;/li&gt;
 
 &lt;/ul&gt;
 &lt;div class="tab-content" data-tab-content&gt;
 
 &lt;div
 class="tab-content-panel active"
 data-tab-panel="preventiva"&gt;
 &lt;h4 id="multitarea-preventiva"&gt;Multitarea Preventiva&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;¿Quién cambia?&lt;/strong&gt; El Sistema Operativo&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mecanismo:&lt;/strong&gt; Time slicing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Herramientas en Python:&lt;/strong&gt; &lt;code&gt;threading&lt;/code&gt;, &lt;code&gt;multiprocessing&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Riesgo principal:&lt;/strong&gt; Condiciones de carrera&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ideal para:&lt;/strong&gt; Cargas CPU-bound o mixtas&lt;/li&gt;
&lt;/ul&gt;

 &lt;/div&gt;
 
 &lt;div
 class="tab-content-panel "
 data-tab-panel="cooperativa"&gt;
 &lt;h4 id="multitarea-cooperativa"&gt;Multitarea Cooperativa&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;¿Quién cambia?&lt;/strong&gt; La propia tarea&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mecanismo:&lt;/strong&gt; &lt;code&gt;await&lt;/code&gt; / yield&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Herramientas en Python:&lt;/strong&gt; &lt;code&gt;asyncio&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Riesgo principal:&lt;/strong&gt; Bloquear el event loop&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ideal para:&lt;/strong&gt; Cargas I/O-bound&lt;/li&gt;
&lt;/ul&gt;

 &lt;/div&gt;
 
 &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="dónde-encaja-asyncio"&gt;¿Dónde encaja &lt;code&gt;asyncio&lt;/code&gt;?&lt;/h2&gt;
&lt;p&gt;Con todos estos conceptos claros, el siguiente diagrama te ayuda a decidir qué herramienta usar según tu caso:&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 A[&amp;#34;¿Qué tipo de operación\nnecesitas optimizar?&amp;#34;] --&amp;gt; B{&amp;#34;¿Es I/O-bound?&amp;#34;}
 B --&amp;gt;|Sí| C{&amp;#34;¿Necesitas manejar\nmuchas conexiones?&amp;#34;}
 C --&amp;gt;|Sí| D[&amp;#34;✅ asyncio&amp;#34;]
 C --&amp;gt;|No| E[&amp;#34;threading o\nasyncio&amp;#34;]
 B --&amp;gt;|No| F{&amp;#34;¿Es CPU-bound?&amp;#34;}
 F --&amp;gt;|Sí| G{&amp;#34;¿Necesitas compartir\nmemoria entre tareas?&amp;#34;}
 G --&amp;gt;|Sí| H[&amp;#34;threading\n+ locks&amp;#34;]
 G --&amp;gt;|No| I[&amp;#34;multiprocessing&amp;#34;]
 F --&amp;gt;|Mixto| J[&amp;#34;asyncio +\nrun_in_executor()&amp;#34;]

 style D fill:#10b981,stroke:#065f46,color:#fff
 style E fill:#10b981,stroke:#065f46,color:#fff
 style H fill:#f59e0b,stroke:#b45309,color:#fff
 style I fill:#3b82f6,stroke:#1e40af,color:#fff
 style J fill:#8b5cf6,stroke:#5b21b6,color:#fff
&lt;/pre&gt;

&lt;h2 id="en-conclusión"&gt;En conclusión&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;asyncio&lt;/code&gt; ofrece &lt;strong&gt;concurrencia&lt;/strong&gt;, no paralelismo — todo corre en un solo hilo.&lt;/li&gt;
&lt;li&gt;Usa &lt;strong&gt;multitarea cooperativa&lt;/strong&gt; — tu código cede control explícitamente con &lt;code&gt;await&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Destaca en cargas &lt;strong&gt;I/O-bound&lt;/strong&gt; — peticiones de red, operaciones de archivo, consultas a bases de datos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No es la solución&lt;/strong&gt; para trabajo CPU-bound — para eso, combínalo con &lt;code&gt;multiprocessing&lt;/code&gt; o usa &lt;a href="https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_in_executor"




 target="_blank"
 


&gt;loop.run_in_executor()&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="referencias"&gt;Referencias&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/asyncio.html"




 target="_blank"
 


&gt;Python &lt;code&gt;asyncio&lt;/code&gt; — Documentación Oficial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/concurrent.futures.html"




 target="_blank"
 


&gt;Python &lt;code&gt;concurrent.futures&lt;/code&gt; — Documentación Oficial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://realpython.com/async-io-python/"




 target="_blank"
 


&gt;Real Python — Async IO in Python: A Complete Walkthrough&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://peps.python.org/pep-3156/"




 target="_blank"
 


&gt;PEP 3156 — Asynchronous IO Support Rebooted&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Skills vs. MCP</title><link>https://blog.dacadev.com/generative-ai/skills-vs-mcp/</link><pubDate>Wed, 29 Apr 2026 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/generative-ai/skills-vs-mcp/</guid><dc:creator>Dacadev</dc:creator><category>IA generativa</category><description>Descubre la diferencia entre Skills y MCP (Model Context Protocol), dos conceptos clave en el desarrollo moderno de agentes de IA. Analizamos cómo trabajan en capas distintas, cuándo usar cada uno y por qué son complementarios y no competidores en la construcción de agentes inteligentes.</description><media:content url="https://blog.dacadev.com/images/generative-ai/skills-vs-mcp/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#el-mcp-model-context-protocol-el-enchufe-universal"&gt;El MCP (Model Context Protocol): el &amp;ldquo;enchufe&amp;rdquo; universal&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#los-skills-relacionado-con-el-comportamiento"&gt;Los Skills: relacionado con el &amp;ldquo;comportamiento&amp;rdquo;&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#la-analogía-del-restaurante"&gt;La analogía del restaurante&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#visualizando-la-arquitectura"&gt;Visualizando la arquitectura&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#cuándo-usar-uno-y-cuándo-usar-el-otro"&gt;Cuándo usar uno y cuándo usar el otro&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#cuándo-usar-mcp"&gt;¿Cuándo usar MCP?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#cuándo-usar-skills"&gt;¿Cuándo usar Skills?&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#los-skills-reemplazan-al-mcp"&gt;¿Los Skills reemplazan al MCP?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conclusión"&gt;Conclusión&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;En el mundo de la &lt;strong&gt;Inteligencia Artificial&lt;/strong&gt;, los términos aparecen y se mezclan con una velocidad que a veces marea incluso a los desarrolladores más experimentados. Dos conceptos de estos conceptos son &lt;strong&gt;Skills&lt;/strong&gt; (habilidades) y &lt;strong&gt;MCP&lt;/strong&gt; (Model Context Protocol).&lt;/p&gt;
&lt;p&gt;¿Son lo mismo? ¿Vienen los &lt;strong&gt;Skills&lt;/strong&gt; a reemplazar al &lt;strong&gt;MCP&lt;/strong&gt;? En este post vamos a desglosar estas tecnologías para entender que, lejos de competir, están diseñadas para trabajar en &lt;strong&gt;capas distintas&lt;/strong&gt; del ecosistema de agentes.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Este artículo busca aclarar estos dos conceptos, sobre todo para quienes están empezando a construir sus primeros agentes y se enfrentan a esta decisión arquitectónica.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="el-mcp-model-context-protocol-el-enchufe-universal"&gt;El MCP (Model Context Protocol): el &amp;ldquo;enchufe&amp;rdquo; universal&lt;/h2&gt;
&lt;p&gt;El &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;, impulsado originalmente por &lt;strong&gt;Anthropic&lt;/strong&gt;, es una capa de &lt;strong&gt;infraestructura&lt;/strong&gt;. Su objetivo es estandarizar cómo un LLM se conecta con el mundo exterior: bases de datos, APIs de Google Drive, Slack, GitHub, etc.&lt;/p&gt;
&lt;p&gt;Imagina que quieres que tu IA lea tus correos. Antes, tenías que escribir un código específico para conectar esa IA con la API de Gmail. Si luego querías usar otra IA, debías repetir el proceso. El &lt;strong&gt;MCP&lt;/strong&gt; actúa como un puerto &lt;strong&gt;USB-C&lt;/strong&gt;: una vez que un servidor (como Gmail) implementa el protocolo &lt;strong&gt;MCP&lt;/strong&gt;, cualquier cliente (un LLM como Claude o GPT) que hable &lt;strong&gt;MCP&lt;/strong&gt; puede conectarse instantáneamente.&lt;/p&gt;
&lt;p&gt;Lo que el &lt;strong&gt;MCP&lt;/strong&gt; resuelve:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Conectividad de datos.&lt;/li&gt;
&lt;li&gt;Exposición de herramientas (Tools).&lt;/li&gt;
&lt;li&gt;Estandarización de recursos externos.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Si te suena familiar, es porque el &lt;strong&gt;MCP&lt;/strong&gt; sigue una filosofía similar a la de protocolos como &lt;strong&gt;HTTP&lt;/strong&gt; o &lt;strong&gt;LSP&lt;/strong&gt; (Language Server Protocol). La idea es siempre la misma: estandarizar para no reinventar la rueda en cada integración.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="los-skills-relacionado-con-el-comportamiento"&gt;Los Skills: relacionado con el &amp;ldquo;comportamiento&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;Si el &lt;strong&gt;MCP&lt;/strong&gt; es el cable que conecta la computadora a la corriente, un &lt;strong&gt;Skill&lt;/strong&gt; es el programa especializado que corre en esa computadora.&lt;/p&gt;
&lt;p&gt;Un &lt;strong&gt;Skill&lt;/strong&gt; es una unidad modular de &lt;strong&gt;lógica de ejecución&lt;/strong&gt;. No se trata solo de &amp;ldquo;tener acceso a una base de datos&amp;rdquo;, sino de saber &lt;strong&gt;cómo procesar&lt;/strong&gt; esa información para cumplir un objetivo específico de negocio. Por ejemplo, &amp;ldquo;Procesar una devolución en un e-commerce&amp;rdquo; es un &lt;strong&gt;Skill&lt;/strong&gt;. Este &lt;strong&gt;Skill&lt;/strong&gt; puede usar varias herramientas &lt;strong&gt;MCP&lt;/strong&gt; para lograr su fin, pero la &amp;ldquo;inteligencia&amp;rdquo; del proceso reside en el &lt;strong&gt;Skill&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Lo que los &lt;strong&gt;Skills&lt;/strong&gt; resuelven:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Encapsulación de flujos de trabajo (Workflows).&lt;/li&gt;
&lt;li&gt;Definición de &amp;ldquo;tono de voz&amp;rdquo; y reglas de negocio.&lt;/li&gt;
&lt;li&gt;Orquestación de múltiples herramientas para una tarea compleja.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="la-analogía-del-restaurante"&gt;La analogía del restaurante&lt;/h2&gt;
&lt;p&gt;Para entenderlo de forma sencilla, imagina un restaurante de alta cocina:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;El sistema de pedidos (MCP):&lt;/strong&gt; Es la infraestructura que permite que la orden llegue de la mesa a la cocina. Es el protocolo que asegura que el camarero y el chef hablen el mismo idioma. No cocina, solo transporta la necesidad y los ingredientes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;El chef especializado (Skill):&lt;/strong&gt; Es quien tiene el conocimiento para transformar los ingredientes en un plato específico (un &amp;ldquo;Skill de Repostería&amp;rdquo; o un &amp;ldquo;Skill de Parrilla&amp;rdquo;). El chef usa las herramientas (cuchillos, hornos, que serían las herramientas expuestas vía MCP) siguiendo una técnica específica para entregar un resultado de calidad.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;El &lt;strong&gt;MCP&lt;/strong&gt; le da a la IA las &lt;strong&gt;&amp;ldquo;manos&amp;rdquo;&lt;/strong&gt; y el &lt;strong&gt;&amp;ldquo;acceso&amp;rdquo;&lt;/strong&gt;, mientras que el &lt;strong&gt;Skill&lt;/strong&gt; le da el &lt;strong&gt;&amp;ldquo;entrenamiento&amp;rdquo;&lt;/strong&gt; y la &lt;strong&gt;&amp;ldquo;lógica&amp;rdquo;&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="visualizando-la-arquitectura"&gt;Visualizando la arquitectura&lt;/h2&gt;
&lt;p&gt;Para los que prefieren ver el flujo de datos, aquí tenemos un diagrama de secuencia que muestra cómo un &lt;strong&gt;Skill&lt;/strong&gt; orquestador utiliza el protocolo &lt;strong&gt;MCP&lt;/strong&gt; para interactuar con el mundo.&lt;/p&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
 participant U as Usuario
 participant LLM as LLM (Cerebro)
 participant S as Skill (Lógica de Negocio)
 participant MCP as MCP Client / Server
 participant DB as Mundo Exterior (API/DB)

 U-&amp;gt;&amp;gt;LLM: &amp;#34;Quiero devolver mi pedido #123&amp;#34;
 LLM-&amp;gt;&amp;gt;S: Activa &amp;#34;Skill de Devoluciones&amp;#34;
 S-&amp;gt;&amp;gt;S: Valida reglas (¿Está en fecha?, ¿Es premium?)
 Note over S: El Skill decide qué acción tomar
 S-&amp;gt;&amp;gt;MCP: Llama a Tool: get_order_details(id: 123)
 MCP-&amp;gt;&amp;gt;DB: Consulta a la base de datos
 DB--&amp;gt;&amp;gt;MCP: Retorna datos del pedido
 MCP--&amp;gt;&amp;gt;S: Envía JSON del pedido
 S-&amp;gt;&amp;gt;S: Procesa lógica final
 S--&amp;gt;&amp;gt;LLM: Confirmación de proceso exitoso
 LLM--&amp;gt;&amp;gt;U: &amp;#34;Tu devolución ha sido procesada con éxito.&amp;#34;
&lt;/pre&gt;

&lt;p&gt;Fíjate en algo importante: el &lt;strong&gt;Skill&lt;/strong&gt; es quien &lt;strong&gt;toma decisiones&lt;/strong&gt;. El &lt;strong&gt;MCP&lt;/strong&gt; solo ejecuta lo que se le pide. Esa diferencia, aunque parezca sutil, es la clave para entender por qué uno no reemplaza al otro.&lt;/p&gt;
&lt;h2 id="cuándo-usar-uno-y-cuándo-usar-el-otro"&gt;Cuándo usar uno y cuándo usar el otro&lt;/h2&gt;
&lt;p&gt;No es una elección de &amp;ldquo;uno u otro&amp;rdquo;, sino de &lt;strong&gt;en qué parte del problema estás trabajando&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Característica&lt;/th&gt;
 &lt;th&gt;MCP (Protocolo)&lt;/th&gt;
 &lt;th&gt;Skill (Habilidad)&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Nivel&lt;/td&gt;
 &lt;td&gt;Bajo / Infraestructura&lt;/td&gt;
 &lt;td&gt;Alto / Cognitivo&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Propósito&lt;/td&gt;
 &lt;td&gt;Integración y acceso&lt;/td&gt;
 &lt;td&gt;Ejecución y decisión&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Reutilización&lt;/td&gt;
 &lt;td&gt;Conectar la IA a cualquier API&lt;/td&gt;
 &lt;td&gt;Aplicar la misma lógica a diferentes IAs&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Ejemplo&lt;/td&gt;
 &lt;td&gt;Conector de base de datos SQL&lt;/td&gt;
 &lt;td&gt;Procesador de reclamos de clientes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="cuándo-usar-mcp"&gt;¿Cuándo usar MCP?&lt;/h3&gt;
&lt;p&gt;Úsalo cuando tu problema es de &lt;strong&gt;acceso a la información&lt;/strong&gt;. Si necesitas que tu IA &amp;ldquo;vea&amp;rdquo; archivos locales, consulte una base de datos en tiempo real o use una herramienta externa de forma estandarizada, ahí es donde el &lt;strong&gt;MCP&lt;/strong&gt; brilla.&lt;/p&gt;
&lt;h3 id="cuándo-usar-skills"&gt;¿Cuándo usar Skills?&lt;/h3&gt;
&lt;p&gt;Úsalo cuando tu problema es de &lt;strong&gt;comportamiento&lt;/strong&gt;. Si necesitas definir cómo debe reaccionar tu agente ante un cliente enfadado, cómo debe seguir un protocolo de seguridad o cómo debe estructurar un reporte complejo combinando datos.&lt;/p&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Una buena regla mental: si la respuesta a &amp;ldquo;¿qué hace falta para resolver esto?&amp;rdquo; es &lt;strong&gt;&amp;ldquo;que la IA pueda hablar con X sistema&amp;rdquo;&lt;/strong&gt;, necesitas &lt;strong&gt;MCP&lt;/strong&gt;. Si la respuesta es &lt;strong&gt;&amp;ldquo;que la IA sepa qué hacer cuando pase Y&amp;rdquo;&lt;/strong&gt;, necesitas un &lt;strong&gt;Skill&lt;/strong&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="los-skills-reemplazan-al-mcp"&gt;¿Los Skills reemplazan al MCP?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Definitivamente no.&lt;/strong&gt; Los &lt;strong&gt;Skills&lt;/strong&gt; se apoyan sobre el &lt;strong&gt;MCP&lt;/strong&gt;. Sin &lt;strong&gt;MCP&lt;/strong&gt; (o una capa de herramientas similar), un &lt;strong&gt;Skill&lt;/strong&gt; sería una lógica &amp;ldquo;ciega&amp;rdquo; que no puede tocar el mundo real. Sin &lt;strong&gt;Skills&lt;/strong&gt;, el &lt;strong&gt;MCP&lt;/strong&gt; es solo un montón de cables conectados que no saben qué construir.&lt;/p&gt;
&lt;p&gt;En el desarrollo moderno de agentes, el objetivo es construir una &lt;strong&gt;librería de Skills&lt;/strong&gt; que definan la identidad y eficiencia de tu empresa, mientras utilizas el ecosistema &lt;strong&gt;MCP&lt;/strong&gt; para asegurar que esos &lt;strong&gt;Skills&lt;/strong&gt; tengan los mejores datos y herramientas disponibles sin tener que reinventar la rueda de la conectividad.&lt;/p&gt;
&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Skills&lt;/strong&gt; y &lt;strong&gt;MCP&lt;/strong&gt; no son rivales: son piezas complementarias del mismo rompecabezas. El &lt;strong&gt;MCP&lt;/strong&gt; resuelve el problema de la &lt;strong&gt;conectividad universal&lt;/strong&gt;, dándole a tu agente acceso estandarizado al mundo. Los &lt;strong&gt;Skills&lt;/strong&gt;, por su parte, encapsulan la &lt;strong&gt;lógica de negocio&lt;/strong&gt; y el &lt;strong&gt;comportamiento&lt;/strong&gt; que hacen único a tu agente.&lt;/p&gt;
&lt;p&gt;Cuando construyes un agente robusto, lo ideal es pensar en capas: una capa de &lt;strong&gt;infraestructura (MCP)&lt;/strong&gt; que te da acceso a las herramientas, y una capa &lt;strong&gt;cognitiva (Skills)&lt;/strong&gt; que decide qué hacer con esas herramientas. Si dominas esta separación, estarás mucho mejor preparado para construir agentes mantenibles, escalables y alineados con las necesidades reales de tu negocio.&lt;/p&gt;</content:encoded></item><item><title>Tipado en Python: Introducción</title><link>https://blog.dacadev.com/python/tipado/introduccion/</link><pubDate>Fri, 09 Aug 2024 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/python/tipado/introduccion/</guid><dc:creator>Dacadev</dc:creator><category>python</category><description>Descubre por qué el tipado en Python es clave para proyectos profesionales. Aprende sobre errores de lógica, validación de tipos y cómo mejorar la calidad de tu código.</description><media:content url="https://blog.dacadev.com/images/python/typing/introduction/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#por-qué-es-importante-el-tipado"&gt;¿Por qué es importante el tipado?&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#tipos-de-errores"&gt;Tipos de errores&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;p&gt;Este artículo hace parte de una serie que explicará el tipado en Python, a continuación puedes ver la recopilación de todos los posts de la serie.
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.dacadev.com/python/tipado/serie-de-tipado" class="btn btn-outline-primary " rel="" &gt;Ver serie&lt;/a&gt;&lt;/p&gt;
&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="por-qué-es-importante-el-tipado"&gt;¿Por qué es importante el tipado?&lt;/h2&gt;
&lt;p&gt;Antes de ahondar en el uso de tipos en python, debemos hacer un pequeño énfasis de porque nace la necesidad de implementar &lt;em&gt;“tipado”&lt;/em&gt; y análisis estático de código en Python&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Escribo tipado entre comillas porque realmente no implementamos tipado en python, sino que simulamos tener tipos en Python, esto lo veremos vas adelante, pero es importante tenerlo en cuenta.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Python, al ser un lenguaje &lt;strong&gt;interpretado&lt;/strong&gt;, significa que el código es leído y ejecutado solamente cuando el interprete pasa por la línea de código, por lo que el error, si existe, solo aparecerá cuando ejecutamos dicha línea de código. Por el contrario en un lenguaje compilado como Go o Java, el código debe primero construido (compilado) y después usado, pero es en el proceso de compilación en donde se realizan validaciones de tipos dentro del código y estas validaciones permiten capturar errores tempranos.&lt;/p&gt;
&lt;h3 id="tipos-de-errores"&gt;Tipos de errores&lt;/h3&gt;
&lt;p&gt;En este punto vale la pena agrupar los errores en dos grupos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Errores de excepción: Son errores que se generan cuando un programa falla al ejecutar una acción determinada, como por ejemplo abrir un archivo que no existe.&lt;/li&gt;
&lt;li&gt;Errores de lógica: Son errores que no generan excepción sino que generan un resultado errado al esperado.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice warning"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Warning&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Los errores de lógica son los mas peligrosos ya que al no levantar una excepción normalmente permiten que el flujo de trabajo continue con los errores.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;hr&gt;
&lt;p&gt;En ese orden de ideas nos centraremos en los errores de &lt;strong&gt;lógica&lt;/strong&gt; ya que son los errores que podemos &lt;em&gt;&amp;ldquo;capturar&amp;rdquo;&lt;/em&gt; gracias a los tipos, por ejemplo con ayuda de tipos podemos capturar errores tempranos como:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;validar el uso de los tipos de datos dentro de nuestro código, por ejemplo si estamos usando un string en un lugar donde deberíamos de usar un entero&lt;/li&gt;
&lt;li&gt;validar que los métodos que estamos llamando existan en el objeto que estamos usando&lt;/li&gt;
&lt;li&gt;validar que los atributos que estamos usando en un objeto existan&lt;/li&gt;
&lt;li&gt;validar que los argumentos que estamos pasando a una función sean los correctos&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Veamos la forma tradicional de validar y capturar errores de tipos en Python. Para ello debemos de implementar una serie sentencias en nuestro código para asegurarnos que estamos usando los tipos correctos. esto puede afectar la legibilidad del código y la productividad, e incluso el rendimiento de nuestros programas en algunos casos.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;clean_text&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;assert&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;isinstance&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;), &lt;span style="color:#98c379"&gt;&amp;#34;Input must be a string&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#7f848e"&gt;# process a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;calculate_sum&lt;/span&gt;(&lt;span style="color:#56b6c2"&gt;*&lt;/span&gt;&lt;span style="color:#e06c75"&gt;nums&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;sum&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; &lt;span style="color:#e06c75"&gt;num&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;in&lt;/span&gt; &lt;span style="color:#e06c75"&gt;nums&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;if&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;not&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;isinstance&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;num&lt;/span&gt;, (&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt;)):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;raise&lt;/span&gt; &lt;span style="color:#e06c75"&gt;ValueError&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Input must be a number&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;sum&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;num&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;sum&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En el caso de &lt;code&gt;clean_text&lt;/code&gt; estamos validando que el argumento &lt;code&gt;a&lt;/code&gt; sea un &lt;code&gt;string&lt;/code&gt;, en caso de que no sea un &lt;code&gt;string&lt;/code&gt;, levantamos una excepción. En el caso de &lt;code&gt;calculate_sum&lt;/code&gt; estamos validando que los argumentos que estamos pasando sean &lt;code&gt;int&lt;/code&gt; o &lt;code&gt;float&lt;/code&gt;, en caso de que no sea alguno de estos, levantamos una excepción.&lt;/p&gt;




 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;En el caso &lt;code&gt;clean_text&lt;/code&gt; estamos usando &lt;code&gt;assert&lt;/code&gt; para validar el tipo de dato, sin embargo &lt;code&gt;assert&lt;/code&gt; no es recomendado para validar tipos de datos, ya que se puede desactivar en tiempo de ejecución, por lo que no es una buena práctica usarlo como captura de errores en código, sin embargo es probable que lo encuentres en tu día a día como desarrollador.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Si miramos a profundidad el código no esta mal, sino que estamos agregando lógica adicional que esta afectando la legibilidad del código, y un de los principales objetivos que tenemos como programadores es escribir código limpio y legible. para los demás o tu yo del futuro. Imagina si hicieramos esto en códigos mas complejos y extensos.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;p&gt;La siguiente entrega de esta seria aborda el tema de como implementar tipado en Python, y como podemos mejorar la legibilidad del código y la productividad.
para verla da click en el siguiente botón.
&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.dacadev.com/python/tipado/tipado-basico" class="btn btn-outline-primary " rel="" &gt;Tipado básico en Python&lt;/a&gt;&lt;/p&gt;
&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>Tipado en Python: Serie de DacaDev</title><link>https://blog.dacadev.com/python/tipado/serie-de-tipado/</link><pubDate>Thu, 08 Aug 2024 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/python/tipado/serie-de-tipado/</guid><dc:creator>Dacadev</dc:creator><category>python</category><description>Descubre cómo el tipado en Python mejora la calidad de tu código, facilita la detección de errores y potencia la escalabilidad de tus proyectos de software. Explora nuestra serie de artículos en DacaDev.</description><media:content url="https://blog.dacadev.com/images/python/typing/serie/banner.png" medium="image" type="image/png"/><content:encoded>&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt;, al ser un lenguaje interpretado y dinámicamente tipado, no incluye de forma nativa la gestión y manejo de tipos. Esta característica es extremadamente útil y práctica, especialmente para quienes están comenzando en el mundo del desarrollo de software.&lt;/p&gt;
&lt;p&gt;Sin embargo, a medida que los proyectos crecen, esta ventaja inicial puede convertirse en un desafío. La ausencia de un sistema de tipos explícito puede complicar la lectura del código, dificultar la depuración de errores y limitar la escalabilidad del proyecto.&lt;/p&gt;
&lt;p&gt;Por esta razón, ha surgido la iniciativa de implementar tipado en &lt;strong&gt;Python&lt;/strong&gt;. Con esta herramienta, los desarrolladores pueden tener un mayor control sobre los tipos de datos en su código, lo que permite capturar errores tempranos y mejorar la calidad del software desde las primeras etapas del desarrollo.&lt;/p&gt;
&lt;p&gt;En &lt;em&gt;DacaDev&lt;/em&gt;, hemos creado una serie de artículos que explican de manera detallada el tipado en &lt;strong&gt;Python&lt;/strong&gt;. A continuación, puedes acceder a cada uno de los artículos de la serie:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.dacadev.com/python/tipado/introduccion"



 


&gt;Introducción al tipado en Python (teoría)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.dacadev.com/python/tipado/tipado-basico"



 


&gt;Tipado básico en Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.dacadev.com/python/tipado/tipado-funciones"



 


&gt;Tipado de funciones en Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.dacadev.com/python/tipado/tipado-clases"



 


&gt;Tipado de clases en Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.dacadev.com/python/tipado/estructuras-de-datos"



 


&gt;Estructuras de datos tipadas en Python&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title>Constantes en Go y conceptos clave</title><link>https://blog.dacadev.com/golang/constants/</link><pubDate>Sun, 09 Jun 2024 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/golang/constants/</guid><dc:creator>Dacadev</dc:creator><category>golang</category><description>Descubre cómo declarar y utilizar constantes en Go para mejorar el rendimiento de tu código. Aprende sobre tipos de constantes, pseudo-enumerados y la poderosa herramienta 'iota' en Golang.</description><media:content url="https://blog.dacadev.com/images/golang/constants/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#constantes-en-go"&gt;Constantes en Go&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#declaración-de-constantes"&gt;Declaración de constantes&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#conceptos-clave-de-las-constantes"&gt;Conceptos clave de las Constantes&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#kind-vs-type"&gt;Kind vs Type&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#pseudo-enumerados"&gt;Pseudo-enumerados&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#iota"&gt;iota&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;En el siguiente artículo aprenderás conceptos clave para entender el funcionamiento de las constantes en &lt;strong&gt;Go&lt;/strong&gt; y algunos conceptos de su funcionamiento que te ayudarán a escribir mejor código.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="constantes-en-go"&gt;Constantes en Go&lt;/h2&gt;
&lt;p&gt;una constante es un valor que no cambia en el tiempo y que puede ser referenciado para efectuar operaciones en un programa. Algo particular de &lt;strong&gt;Go&lt;/strong&gt; es que las constantes solo existen en tiempo de compilación. Como sabrás, &lt;strong&gt;Go&lt;/strong&gt; es un lenguaje de programación compilado, por lo que para obtener el código final del programa debemos construirlo. Es aquí donde las constantes son transformadas en valores literales dentro del programa.&lt;/p&gt;
&lt;p&gt;Esto implica que durante la ejecución del código, las constantes no son alojadas en un espacio de memoria como ocurre con otros lenguajes como &lt;em&gt;JavaScript&lt;/em&gt;, sino que son valores quemados en el binario final. Esto optimiza el rendimiento del programa y evita que se alojen valores en memoria que no son necesarios.&lt;/p&gt;
&lt;h2 id="declaración-de-constantes"&gt;Declaración de constantes&lt;/h2&gt;
&lt;p&gt;En &lt;strong&gt;Go&lt;/strong&gt;, la forma de declarar constantes es muy simple y similar a otros lenguajes de programación. Tenemos varias maneras de hacerlo. Veamos cada uno de los casos:&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Las constantes en &lt;strong&gt;Go&lt;/strong&gt; solo pueden hacer referencia a tipos de dato built-in del lenguaje.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// single constant&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;miConstante&lt;/span&gt; = &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// multi-assignment in one line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;c&lt;/span&gt; = &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// multi-assignment in block&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;anotherConstant&lt;/span&gt; = &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;stringConstant&lt;/span&gt; = &lt;span style="color:#98c379"&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;finalConstant&lt;/span&gt; = &lt;span style="color:#e5c07b"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="conceptos-clave-de-las-constantes"&gt;Conceptos clave de las Constantes&lt;/h2&gt;
&lt;h3 id="kind-vs-type"&gt;Kind vs Type&lt;/h3&gt;
&lt;p&gt;En &lt;strong&gt;Go&lt;/strong&gt;, las constantes pueden ser de dos tipos, conocidos como &lt;code&gt;kind&lt;/code&gt; y &lt;code&gt;type&lt;/code&gt;. La principal diferencia es que en una constante de tipo &lt;code&gt;kind&lt;/code&gt; no se necesita especificar el tipo de dato que se está utilizando, mientras que en una constante de tipo &lt;code&gt;type&lt;/code&gt; sí es necesario especificarlo. Esto lo podemos observar en el siguiente ejemplo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// kind&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;name&lt;/span&gt; = &lt;span style="color:#98c379"&gt;&amp;#34;John&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt; = &lt;span style="color:#d19a66"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// type&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;c&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;int64&lt;/span&gt; = &lt;span style="color:#d19a66"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;d&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float32&lt;/span&gt; = &lt;span style="color:#d19a66"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La principal ventaja del uso de &lt;code&gt;kind&lt;/code&gt; vs &lt;code&gt;type&lt;/code&gt; se ve en tiempo de compilación. Este comportamiento se definirá en base al tipo de constante usado:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;kind&lt;/strong&gt;: El compilador hará un análisis para determinar cuál es el tipo de dato más óptimo para efectuar la operación definida.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;type&lt;/strong&gt;: El compilador no hará ninguna inferencia o análisis sobre cuál debe ser la operación a realizar, sino que siempre usará el mismo tipo de valor (tipo) en la constante.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Esto es importante porque, recuerda, &lt;strong&gt;Go&lt;/strong&gt; no convierte valores automáticamente. Si vas a usar la constante para operar con otros tipos de datos, deberás efectuar la transformación requerida explícitamente.&lt;/p&gt;
&lt;p&gt;Veamos algunos ejemplos con constantes de tipo &lt;code&gt;kind&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;package&lt;/span&gt; &lt;span style="color:#e06c75"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;func&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt; = &lt;span style="color:#d19a66"&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#c678dd"&gt;var&lt;/span&gt; &lt;span style="color:#e06c75"&gt;bigNumber&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;int32&lt;/span&gt; = &lt;span style="color:#d19a66"&gt;1000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;agePlusNumber&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;:=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;bigNumber&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;fmt&lt;/span&gt;.&lt;span style="color:#61afef;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;El resultado es: %d\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;agePlusNumber&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;fmt&lt;/span&gt;.&lt;span style="color:#61afef;font-weight:bold"&gt;Println&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;El tipo de dato de cada variable es:&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;fmt&lt;/span&gt;.&lt;span style="color:#61afef;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;age: %T\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;fmt&lt;/span&gt;.&lt;span style="color:#61afef;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;bigNumber: %T\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;bigNumber&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;fmt&lt;/span&gt;.&lt;span style="color:#61afef;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;agePlusNumber: %T\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;agePlusNumber&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El resultado del anterior ejemplo es:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#56b6c2"&gt;[&lt;/span&gt;Running&lt;span style="color:#56b6c2"&gt;]&lt;/span&gt; go run &lt;span style="color:#98c379"&gt;&amp;#34;/home/dacacode/dacadev/test/tempCodeRunnerFile.go&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;El resultado es: &lt;span style="color:#d19a66"&gt;1020&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;El tipo de dato de cada variable es:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;age: int
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;bigNumber: int32
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;agePlusNumber: int32
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Como puedes observar, el tipo de &lt;code&gt;age&lt;/code&gt; es &lt;code&gt;int&lt;/code&gt;, mientras que el de &lt;code&gt;bigNumber&lt;/code&gt; y &lt;code&gt;agePlusNumber&lt;/code&gt; es &lt;code&gt;int32&lt;/code&gt;, debido a que el compilador define cuál es el tipo más óptimo.&lt;/p&gt;
&lt;p&gt;Ahora veamos el mismo caso usando constantes de tipo &lt;code&gt;type&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;package&lt;/span&gt; &lt;span style="color:#e06c75"&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;func&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;int8&lt;/span&gt; = &lt;span style="color:#d19a66"&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#c678dd"&gt;var&lt;/span&gt; &lt;span style="color:#e06c75"&gt;bigNumber&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;int32&lt;/span&gt; = &lt;span style="color:#d19a66"&gt;1000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;agePlusNumber&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;:=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;age&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;bigNumber&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;fmt&lt;/span&gt;.&lt;span style="color:#61afef;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;El resultado es: %d\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;agePlusNumber&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;fmt&lt;/span&gt;.&lt;span style="color:#61afef;font-weight:bold"&gt;Println&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;El tipo de dato de cada variable es:&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;fmt&lt;/span&gt;.&lt;span style="color:#61afef;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;age: %T\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;age&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;fmt&lt;/span&gt;.&lt;span style="color:#61afef;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;bigNumber: %T\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;bigNumber&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;fmt&lt;/span&gt;.&lt;span style="color:#61afef;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;agePlusNumber: %T\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;agePlusNumber&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El código no se podrá compilar e incluso el IDE nos debería mostrar un error ya que &lt;strong&gt;Go&lt;/strong&gt; nos dirá que la operación enter un tipo de dato y otro no esta permitido, el erro deberá lucir como el siguiente:&lt;/p&gt;




 
 
 
 &lt;div class="flex justify-center"&gt;
 &lt;img
 src="https://blog.dacadev.com/images/golang/constants/const-type-error_hu_b522ac4d59b0f1f3.webp"
 alt="Imagen guia del contenido de la página"/&gt;
 &lt;/div&gt;
 
 
 


&lt;h3 id="pseudo-enumerados"&gt;Pseudo-enumerados&lt;/h3&gt;
&lt;p&gt;Una funcionalidad que podemos aprovechar de las constantes y tipos definidos por el usuario es la creación de lo que podemos denominar &lt;em&gt;pseudo-enumerados&lt;/em&gt;. En &lt;strong&gt;Go&lt;/strong&gt; no disponemos de una estructura de datos de tipo &lt;code&gt;Enum&lt;/code&gt;. sin embargo, podemos emularlas (ojo, no es que sean &lt;code&gt;Enums&lt;/code&gt; en la práctica, pero pueden cumplir funciones similares).&lt;/p&gt;
&lt;p&gt;La creación de estos enumerados es sencilla y consiste en definir un tipo de dato personalizado y posteriormente declarar las constantes con este tipo de dato. Para entenderlo mejor, veamos un ejemplo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UserPermissions&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;Admin&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UserPermissions&lt;/span&gt; = &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;Read&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UserPermissions&lt;/span&gt; = &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;Write&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UserPermissions&lt;/span&gt; = &lt;span style="color:#d19a66"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;func&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;validateUserPermissions&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;permissions&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UserPermissions&lt;/span&gt;) &lt;span style="color:#e5c07b"&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#7f848e"&gt;// hacer algo con el código&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En el ejemplo podemos ver que al crear el tipo &lt;code&gt;UserPermissions&lt;/code&gt; y luego constantes de este mismo tipo, estamos usando una constante de tipo &lt;code&gt;type&lt;/code&gt;. De esta manera podríamos controlar y exportar estas constantes del paquete. Sin embargo, no olvides que es una emulación de enumeración.&lt;/p&gt;
&lt;h3 id="iota"&gt;iota&lt;/h3&gt;
&lt;p&gt;Quiero hacer énfasis en la declaración de las constantes en el bloque del anterior ejemplo. En ellas podemos observar el uso de un valor numérico secuencial, es decir, que empieza desde 0, 1, 2, &amp;hellip; Esto es importante porque &lt;strong&gt;Go&lt;/strong&gt; nos ofrece una forma rápida y sencilla de realizar este mismo proceso de manera automática. Para ello tenemos el concepto de &lt;code&gt;iota&lt;/code&gt;, que nos permite declarar la secuencia de constantes en bloque empezando desde cero.&lt;/p&gt;
&lt;p&gt;Veamos algunos ejemplos:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;A&lt;/span&gt; = &lt;span style="color:#e5c07b"&gt;iota&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;B&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;C&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;func&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;fmt&lt;/span&gt;.&lt;span style="color:#61afef;font-weight:bold"&gt;Println&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;A&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;B&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;C&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// 0 1 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En el ejemplo anterior, podemos observar que estamos declarando las constantes &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt;, y &lt;code&gt;C&lt;/code&gt; y estas tendrán el valor de 0, 1 y 2 respectivamente. Lo que debemos destacar es el uso de la sintaxis &lt;code&gt;iota&lt;/code&gt;. Si ejecutamos el código, veremos el siguiente resultado:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#56b6c2"&gt;[&lt;/span&gt;Running&lt;span style="color:#56b6c2"&gt;]&lt;/span&gt; go run &lt;span style="color:#98c379"&gt;&amp;#34;/home/dacacode/dacadev/test/main.go&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d19a66"&gt;0&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt; &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;De igual manera, podemos agregar operadores al valor de &lt;code&gt;iota&lt;/code&gt;, siempre teniendo claro que el valor inicia en cero y es incremental de a 1 unidad. Veamos unos ejemplos:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;KB&lt;/span&gt; = &lt;span style="color:#d19a66"&gt;1&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;lt;&amp;lt;&lt;/span&gt; (&lt;span style="color:#d19a66"&gt;10&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;iota&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;// 1 &amp;lt;&amp;lt; (10*0) = 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;MB&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 1 &amp;lt;&amp;lt; (10*1) = 1024&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;GB&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 1 &amp;lt;&amp;lt; (10*2) = 1048576&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;TB&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 1 &amp;lt;&amp;lt; (10*3) = 1073741824&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;A&lt;/span&gt; = &lt;span style="color:#e5c07b"&gt;iota&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;B&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;C&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;D&lt;/span&gt; = &lt;span style="color:#e5c07b"&gt;iota&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;E&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;F&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;También podemos saltarnos los valores secuenciales de &lt;code&gt;iota&lt;/code&gt; si estos no fueran necesarios empleando el caracter &lt;code&gt;_&lt;/code&gt; para ignorar el valor. Veamos un ejemplo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;_&lt;/span&gt; = &lt;span style="color:#e5c07b"&gt;iota&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// Ignora el valor 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;One&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;Two&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;Three&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;_&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// Ignora el valor 4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;Five&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;Ten&lt;/span&gt; = &lt;span style="color:#e5c07b"&gt;iota&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt; &lt;span style="color:#d19a66"&gt;2&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 6 * 2 = 12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;Eleven&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 7 * 2 = 14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Con el concepto de &lt;code&gt;iota&lt;/code&gt; ya claro, podemos facilitar la escritura de &lt;em&gt;pseudo-enumeraciones&lt;/em&gt; de la siguiente manera:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;type&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UserPermissions&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;Admin&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UserPermissions&lt;/span&gt; = &lt;span style="color:#e5c07b"&gt;iota&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;Read&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UserPermissions&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#e06c75"&gt;Write&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UserPermissions&lt;/span&gt; &lt;span style="color:#7f848e"&gt;// 3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;func&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;validateUserPermissions&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;permissions&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UserPermissions&lt;/span&gt;) &lt;span style="color:#e5c07b"&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#7f848e"&gt;// hacer algo con el código&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;El término proviene de la letra griega &lt;code&gt;ι&lt;/code&gt; (iota), que es la novena letra del alfabeto griego. Históricamente, la letra iota se usa en matemáticas y lógica para representar el elemento más pequeño en un conjunto o una secuencia, lo cual es apropiado dada su función en &lt;strong&gt;Go&lt;/strong&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>MicroPython: Manejo de pines</title><link>https://blog.dacadev.com/micropython/pines/</link><pubDate>Wed, 08 May 2024 09:00:00 +0000</pubDate><guid>https://blog.dacadev.com/micropython/pines/</guid><dc:creator>Dacadev</dc:creator><category>micropython</category><description>Aprende a manejar los pines con la clase Pin de MicroPython. Descubre cómo configurar, usar y sacar el máximo provecho de tu RP2040.</description><media:content url="https://blog.dacadev.com/images/micropython/pins/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#qué-es-la-clase-pin"&gt;¿Qué es la clase &lt;code&gt;Pin&lt;/code&gt;?&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#instancia-de-la-clase-pin"&gt;Instancia de la Clase &lt;code&gt;Pin&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#métodos-de-la-clase-pin"&gt;Métodos de la Clase &lt;code&gt;Pin&lt;/code&gt;&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#pininit"&gt;Pin.init&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#pinvalue"&gt;Pin.value&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#pinon"&gt;Pin.on()&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#pinoff"&gt;Pin.off()&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#pintoggle"&gt;Pin.toggle()&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#pinirq"&gt;Pin.irq()&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#ejemplos-prácticos-de-pin-con-rp2040"&gt;Ejemplos prácticos de &lt;code&gt;Pin&lt;/code&gt; con RP2040&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;En este artículo aprenderás que es la clase &lt;code&gt;Pin&lt;/code&gt; de &lt;em&gt;Micropython 🐍&lt;/em&gt; y como esta gestiona las diferentes funcionalidades genéricas de los pines de cualquier tipo de chip. Además, verás ejemplos de cómo configurarla y usarla con la &lt;strong&gt;RP2040&lt;/strong&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="qué-es-la-clase-pin"&gt;¿Qué es la clase &lt;code&gt;Pin&lt;/code&gt;?&lt;/h2&gt;
&lt;p&gt;Empecemos definiendo qué es un &lt;strong&gt;pin&lt;/strong&gt; dentro de nuestro microcontrolador (&lt;strong&gt;uM&lt;/strong&gt;), un &lt;strong&gt;pin&lt;/strong&gt; hace referencia a una interfaz I/O asociada a un &lt;strong&gt;pin&lt;/strong&gt; físico de nuestro &lt;strong&gt;uM&lt;/strong&gt;. Con él podemos interactuar con el mundo real, ya sea leyendo o escribiendo señales digitales, o incluso analógicas.&lt;/p&gt;
&lt;p&gt;La clase &lt;code&gt;Pin&lt;/code&gt; es una de las principales clases que provee &lt;em&gt;Micropython 🐍&lt;/em&gt;, ya que es la que nos permitirá interactuar con los pines de nuestros &lt;strong&gt;uM&lt;/strong&gt;. Esta clase se encuentra en el paquete &lt;code&gt;machine&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="instancia-de-la-clase-pin"&gt;Instancia de la Clase &lt;code&gt;Pin&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;La clase &lt;code&gt;Pin&lt;/code&gt;, tiene la siguiente firma de constructor&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Pin&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;id&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;mode&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=-&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;pull&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=-&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;value&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;drive&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;alt&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=-&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En donde:&lt;/p&gt;
&lt;p&gt;controla cuál será el comportamiento del pin. En Micropython 🐍 encuentras constantes que te ayudan a establecer el funcionamiento:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;id&lt;/code&gt; es el unico parámetro obligatorio y hace referencia al pin que quieres controlar. Cada &lt;strong&gt;uM&lt;/strong&gt; tiene su propio mapeo de pines, por lo que deberás de consultar la documentación de tu &lt;strong&gt;uM&lt;/strong&gt; para saber que pines puedes controlar.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mode&lt;/code&gt;* controla cuál será el comportamiento del pin. En *Micropython 🐍* encuentras constantes que te ayudan a establecer el funcionamiento:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Pin.IN&lt;/code&gt; establece el pin como entrada.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pin.OUT&lt;/code&gt; establece el pin como salida.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pin.OPEN_DRAIN&lt;/code&gt; establece el pin como salida de tipo &lt;em&gt;Open-drain&lt;/em&gt; (colector abierto), lo que significa que, si la salida está en nivel bajo, es un cero lógico, y si está en alto (1), se configura como alta impedancia.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pin.ALT&lt;/code&gt; establece el pin para funcionar de manera alterna, utilizando un propósito específico del hardware.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pin.ALT_OPEN_DRAIN&lt;/code&gt; es la combinación de &lt;code&gt;Pin.ALT&lt;/code&gt; y &lt;code&gt;Pin.OPEN_DRAIN&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pin.ANALOG&lt;/code&gt; establece el pin como entrada analógica&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pull&lt;/code&gt;* activas o no la opción de usar una resistencia de &lt;strong&gt;pull-up&lt;/strong&gt; o &lt;strong&gt;pull-down&lt;/strong&gt;, sus opciones validas son:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Pin.PULL_UP&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pin.PULL_DOWN&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;None&lt;/code&gt; = No se activa ninguna resistencia, es el valor por defecto&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;value&lt;/code&gt; es el valor inicial que quieres asignar al pin y solo funciona cuando el pin es configurado como salida, es decir que &lt;code&gt;Pin.OUT&lt;/code&gt; o &lt;code&gt;Pin.OPEN_DRAIN&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;drive&lt;/code&gt; se utiliza para especificar la fuerza de la salida del pin. Esto es importante cuando conectas el pin a circuitos que tienen diferentes requerimientos de corriente. Los valores típicos para drive son algo así como Pin.DRIVE_0, Pin.DRIVE_1, etc., donde los números más altos representan una mayor capacidad de corriente de salida.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alt&lt;/code&gt;* cuando el pin está configurado como Pin.ALT o Pin.ALT_OPEN_DRAIN, este parámetro se utiliza para especificar la función alternativa que se desea utilizar.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;* No todos los pines tiene disponibles todas las configuraciones descritas, para validarlo debes de consultar la documentación de tu &lt;strong&gt;uM&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="métodos-de-la-clase-pin"&gt;Métodos de la Clase &lt;code&gt;Pin&lt;/code&gt;&lt;/h2&gt;
&lt;h3 id="pininit"&gt;Pin.init&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;init&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;mode&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=-&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;pull&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=-&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;value&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;drive&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;alt&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=-&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Una vez tengas una instancia de la clase &lt;code&gt;Pin&lt;/code&gt;, puedes cambiar su configuración inicial usando el método &lt;code&gt;init&lt;/code&gt; el cual recibe los mismos atributos del constructor salvo el identificador &lt;code&gt;id&lt;/code&gt;. Un ejemplo de su uso sería&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;machine&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;led&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;25&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;led&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;init&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;mode&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;OUT&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;value&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En el ejemplo anterior, estoy creando una instancia asociada al pin 25 (mapeado de mi &lt;strong&gt;uM&lt;/strong&gt;) y posteriormente configurándolo con el método &lt;code&gt;init&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="pinvalue"&gt;Pin.value&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;value&lt;/span&gt;([&lt;span style="color:#e06c75"&gt;x&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Este método se utiliza para leer o escribir el valor del pin. Si no se pasa ningún parámetro, el método se comporta como un lector. Si se pasa un valor, el método se comporta como un escritor. Un ejemplo de su uso sería&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;machine&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;led&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;25&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;OUT&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;led&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;value&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;led&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;value&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En el ejemplo, estamos creando un pin como salida y configurando su valor a 1, para luego leer el valor del pin.&lt;/p&gt;
&lt;h4 id="pinon"&gt;Pin.on()&lt;/h4&gt;
&lt;p&gt;Este método es un atajo para configurar el valor del pin a 1, es decir, que el pin se configura en alto, lo cual sería lo mismo que hacer:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;value&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="pinoff"&gt;Pin.off()&lt;/h4&gt;
&lt;p&gt;Este método es un atajo para configurar el valor del pin a 0, es decir, que el pin se configura en bajo, lo cual sería lo mismo que hacer:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;value&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="pintoggle"&gt;Pin.toggle()&lt;/h4&gt;
&lt;p&gt;Este método es un atajo para cambiar el valor del pin. Si el pin está en 1, lo cambia a 0 y viceversa, lo cual sería lo mismo que hacer:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;value&lt;/span&gt;(&lt;span style="color:#56b6c2"&gt;not&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;value&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="pinirq"&gt;Pin.irq()&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;irq&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;handler&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;trigger&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;IRQ_FALLING&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Pin&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;IRQ_RISING&lt;/span&gt;, &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;priority&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;wake&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;hard&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e5c07b"&gt;False&lt;/span&gt;)¶
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Este método es muy importante, ya que sirve para configurar los pines para que sean asociados a interrupciones y poder ejecutar un &lt;code&gt;callback&lt;/code&gt; cuando se cumpla una condición. Los parámetros que recibe son:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;handler&lt;/code&gt;: Es un &lt;code&gt;callable&lt;/code&gt; de python, es decir, una función o método de clase que recibe como parámetro únicamente un objeto de tipo &lt;code&gt;Pin&lt;/code&gt;, que será la instancia del pin que activó la interrupción.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;trigger&lt;/code&gt;: A través de este atributo controlaremos el tipo de comportamiento que se deberá cumplir para activar la interrupción. Para entender los posibles valores que podemos asignar, veamos primero cómo es una señal digital.Una señal digital oscila entre dos valores, 0 o 1, y la transición entre esos valores es lo que llamamos flancos. Como hay dos valores, tenemos 2 tipos de flancos. Los flancos de subida ocurren cuando cambiamos de 0 a 1 y los flancos de bajada cuando cambiamos de 1 a 0. De esta manera, en Micropython encontramos 4 tipos de activadores que podemos configurar en nuestra interrupción por pin:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Pin.IRQ_FALLING&lt;/code&gt;: Configura la interrupción para que se active cuando el pin cambie de 1 a 0&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pin.IRQ_RISING&lt;/code&gt;: Configura la interrupción para que se active cuando el pin cambie de 0 a 1&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pin.IRQ_LOW_LEVEL&lt;/code&gt;: Configura la interrupción para que se active cuando el pin se encuentre en 0&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pin.IRQ_HIGH_LEVEL&lt;/code&gt;: Configura la interrupción para que se active cuando el pin se encuentre en 1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En el siguiente diagrama puedes visualizar las fases de la señal:&lt;/p&gt;

 
 
 
 
 
 
 &lt;div class="flex justify-center"&gt;
 &lt;img
 src="https://blog.dacadev.com/images/micropython/pins/trigger-types_hu_2fa10276e580adee.webp"
 alt="Imagen guia del contenido de la página"style="width:400px"/&gt;
 &lt;/div&gt;
 
 
 
 

&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;En el siguiente &lt;a href="https://blog.dacadev.com/micropython/interrupciones"



 


&gt;artículo&lt;/a&gt; te explico más del tema de interrupciones con &lt;em&gt;Micropython 🐍&lt;/em&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="ejemplos-prácticos-de-pin-con-rp2040"&gt;Ejemplos prácticos de &lt;code&gt;Pin&lt;/code&gt; con RP2040&lt;/h2&gt;
&lt;p&gt;En el siguiente embebido estamos creando un proyecto en la plataforma &lt;a href="https://wokwi.com/"




 target="_blank"
 


&gt;Wokwi&lt;/a&gt;, que nos permite simular proyectos con tarjetas como Arduino Uno, ESP32, Raspberry Pi Pico, entre otras, junto con un amplio conjunto de sensores y actuadores. En este caso, estamos utilizando una Raspberry Pi Pico y conjunto de LEDs y botones para mostrar cómo se puede controlar un pin con la clase &lt;code&gt;Pin&lt;/code&gt; de &lt;em&gt;Micropython 🐍&lt;/em&gt;&lt;/p&gt;
&lt;iframe
 src="https://wokwi.com/projects/396825205015340033"
 height="600"
 width="100%"
 title="Ejemplo RP Pines"
 loading="lazy"&gt;
&lt;/iframe&gt;
&lt;p&gt;En el ejemplo podemos ver 4 casos de uso sencillos para la clase &lt;code&gt;Pin&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Caso 1&lt;/strong&gt;: Configuramos un pin como salida y lo encendemos en la función &lt;code&gt;main&lt;/code&gt; en un intervalo de 500ms con la fuinción &lt;code&gt;sleep&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Caso 2&lt;/strong&gt;: Declaramos un pin como salida, pero primero instanciamos la clase &lt;code&gt;Pin&lt;/code&gt; y luego configuramos el pin con el método &lt;code&gt;init&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Case 3&lt;/strong&gt;: Configuramos dos pines con la clase &lt;code&gt;Pin&lt;/code&gt;, uno como salida y otro como entrada. Leemos el valor del pin de entrada y lo asignamos al pin de salida&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Caso 4&lt;/strong&gt;: Configuramos un pin como entrada y configuramos una interrupción para que se active cuando el pin cambie de 0 a 1. En el &lt;code&gt;callback&lt;/code&gt; simplemente cambiamos el valor del pin de salida.&lt;/li&gt;
&lt;/ol&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;ul&gt;
&lt;li&gt;En el siguiente &lt;a href="https://wokwi.com/projects/396825205015340033"




 target="_blank"
 


&gt;enlace&lt;/a&gt; puedes ver el código fuente del proyecto en una nueva pestaña.&lt;/li&gt;
&lt;li&gt;El caso 4 de nuestro proyecto funciona con interrupciones, y es posible que en la simulación no funcione correctamente debido a que no se está procesando el debounce del botón.&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;





 
 





 


&lt;div class="notice info"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Info&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Podrás encontrar toda la documentación de la clase Pin para &lt;em&gt;micropython 🐍&lt;/em&gt; en el siguiente &lt;a href="https://docs.micropython.org/en/latest/library/machine.Pin.html#machine.Pin"




 target="_blank"
 


&gt;&lt;strong&gt;link&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>Patrones de Diseño: Decorador</title><link>https://blog.dacadev.com/programacion/patrones-de-diseno/decorador/</link><pubDate>Wed, 21 Feb 2024 21:25:17 +0000</pubDate><guid>https://blog.dacadev.com/programacion/patrones-de-diseno/decorador/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Explora el patrón decorador en diseño de software: una guía completa para agregar dinamismo y flexibilidad a tus objetos, evitando la complejidad del código.</description><media:content url="https://blog.dacadev.com/images/programming/design-patterns/decorator/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#objetivo-del-patrón-decorador"&gt;Objetivo del patrón decorador&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#ejemplo-de-uso"&gt;Ejemplo de uso&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#características-del-patrón-decorador"&gt;Características del patrón decorador&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#implementación-del-ejemplo-en-código"&gt;Implementación del ejemplo en código&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#teoría"&gt;Teoría&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#ejemplo"&gt;Ejemplo&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#consideraciones-del-patrón-decorador"&gt;Consideraciones del patrón decorador&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;h2 id="objetivo-del-patrón-decorador"&gt;Objetivo del patrón decorador&lt;/h2&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;El &lt;strong&gt;patrón decorador&lt;/strong&gt; agrega dinamismo a la extensión de funcionalidades.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;El objetivo del &lt;strong&gt;patrón decorador&lt;/strong&gt; es crear una clase abstracta, la cual usaremos para crear (a través de herencia) los objetos base. Los decoradores serán clases especiales que extienden las funcionalidades de la clase abstracta, agregando un campo que contendrá una instancia de la clase abstracta, o en su defecto, un hijo de la misma.&lt;/p&gt;
&lt;p&gt;Veamos un ejemplo de cómo los decoradores pueden funcionar. Supongamos que estamos creando una aplicación para llevar el control de costos de bebidas, donde el costo de estas bebidas depende de los ingredientes adicionales que le añadamos, como por ejemplo, chocolate rallado, crema, etc.&lt;/p&gt;
&lt;h2 id="ejemplo-de-uso"&gt;Ejemplo de uso&lt;/h2&gt;
&lt;p&gt;Ahora, supongamos que tenemos una clase base café a la cual queremos agregar dos ingredientes nuevos: chocolate y crema chantilly. Gráficamente, se vería algo como&lt;/p&gt;




 
 
 
 &lt;div class="flex justify-center"&gt;
 &lt;img
 src="https://blog.dacadev.com/images/programming/design-patterns/decorator/decorator-examples_hu_96ec4daeb7afeea5.webp"
 alt="Imagen guia del contenido de la página"style="width:400px"/&gt;
 &lt;/div&gt;
 
 
 


&lt;p&gt;De este ejemplo, podemos ver que para calcular el costo total de la bebida debemos sumar el valor de costo de cada uno de los decoradores o de las clases decoradoras. Para ello, la clase base debe tener la capacidad de identificar si tiene un hijo para retornar su valor de costo por defecto y así encadenar la suma.&lt;/p&gt;
&lt;p&gt;Antes de pasar al código de implementación, veamos algunas características que debemos tener en cuenta para este patrón.&lt;/p&gt;
&lt;h2 id="características-del-patrón-decorador"&gt;Características del patrón decorador&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;El decorador debe tener el mismo supertipo que el objeto que están decorando; es decir, ambas clases, la clase decoradora y la que se está decorando, deben heredar de la misma clase.&lt;/li&gt;
&lt;li&gt;Puedes usar uno o más decoradores para encapsular un objeto, lo que significa que no hay límite en la cantidad de objetos decoradores que se utilicen sobre un objeto.&lt;/li&gt;
&lt;li&gt;Cuando se le da el mismo supertipo al decorado y a la clase que está decorando, podemos pasar dicho elemento decorado en lugar del objeto original encapsulado.&lt;/li&gt;
&lt;li&gt;El decorador agrega su propio comportamiento antes o después de que el objeto decorado realice su trabajo.&lt;/li&gt;
&lt;li&gt;Los objetos pueden ser decorados en cualquier momento, lo que permite que sean decorados de manera dinámica en tiempo de ejecución.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 El &lt;strong&gt;patrón decorador&lt;/strong&gt; adiciona responsabilidades de manera dinámica a un objeto, ofreciendo flexibilidad y una alternativa al uso de subclases.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="implementación-del-ejemplo-en-código"&gt;Implementación del ejemplo en código&lt;/h2&gt;
&lt;h3 id="teoría"&gt;Teoría&lt;/h3&gt;
&lt;p&gt;Para la implementación de nuestro ejemplo, veamos como funcionaría el diagrama de clases&lt;/p&gt;
&lt;pre class="mermaid"&gt;classDiagram
 class Component {
 methodA()
 methodB()
 otherMethods()
 }
 class ConcreteComponent {
 methodA()
 methodB()
 }
 class Decorator {
 WrappedObj Component
 methodA()
 methodB()
 otherMethods()
 }
 class ConcreteDecoratorA {
 WrappedObj Component
 methodA()
 methodB()
 otherMethods()
 }
 class ConcreteDecoratorB {
 WrappedObj Component
 methodA()
 methodB()
 otherMethods()
 }
 Component &amp;lt;|-- ConcreteComponent
 Component &amp;lt;|-- Decorator
 Decorator &amp;lt;|-- ConcreteDecoratorA
 Decorator &amp;lt;|-- ConcreteDecoratorB
&lt;/pre&gt;

&lt;p&gt;Tendremos una clase base (nuestra clase abstracta) que en el diagrama se llama Component. De esta clase creamos dos clases: una es la clase &lt;code&gt;ConcreteComponent&lt;/code&gt;, que es la que usaremos para instanciar nuestros objetos, y otra clase llamada &lt;code&gt;Decorator&lt;/code&gt;, que es la que usaremos para crear todos los decoradores que podemos usar con nuestro objeto &lt;code&gt;ConcreteComponent&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Decorator&lt;/code&gt; es una clase abstracta que será usada para crear nuestros decoradores específicos. Esta clase definirá los métodos y demás lógica que debe ser implementada para que otras clases sean decoradores válidos.&lt;/p&gt;
&lt;h3 id="ejemplo"&gt;Ejemplo&lt;/h3&gt;
&lt;p&gt;Aplicando el anterior esquema a un ejemplo, podemos suponer que queremos crear tipos de bebidas que varían su combinación&lt;/p&gt;
&lt;pre class="mermaid"&gt;classDiagram
 class Beverage {
 -description
 +getDescription()
 +cost()
 }
 class Coffee {
 +cost()
 }
 class Decaf {
 +cost()
 }
 class HouseBlend {
 +cost()
 }
 class IngredientDecorator {
 -beverage Beverage
 +getDescription()
 }
 class Milk {
 +cost()
 +getDescription()
 }
 class Mocha {
 +cost()
 +getDescription()
 }
 class Soy {
 +cost()
 +getDescription()
 }
 class Chantilly {
 +cost()
 +getDescription()
 }
 class Chocolate {
 +cost()
 +getDescription()
 }
 Beverage &amp;lt;|-- Coffee
 Beverage &amp;lt;|-- Decaf
 Beverage &amp;lt;|-- HouseBlend
 Beverage &amp;lt;|-- IngredientDecorator
 IngredientDecorator &amp;lt;|-- Milk
 IngredientDecorator &amp;lt;|-- Mocha
 IngredientDecorator &amp;lt;|-- Soy
 IngredientDecorator &amp;lt;|-- Chantilly
 IngredientDecorator &amp;lt;|-- Chocolate
&lt;/pre&gt;

&lt;p&gt;La implementación del anterior diagrama se haría de la siguiente manera (en Python) empezaremos por la implementación de las clases abstractas&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;abc&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Beverage&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;cost&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;description&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;IngredientDecorator&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;beverage&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Beverage&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;beverage&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;beverage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;cost&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;description&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ahora haciendo uso de nuestras clases abstractas, podemos crear nuestros objetos y decoradores concretos, nuestros objetos lucirían de la siguiente forma:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;abc_classes&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Beverage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Coffee&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Beverage&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;cost&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1.99&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;description&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;Coffee&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Decaf&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Beverage&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;cost&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#d19a66"&gt;1.25&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;description&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;Decaf&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;HouseBlend&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Beverage&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;cost&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.89&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;description&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;House Blend&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;y nuestros decoradores&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;abc_classes&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;IngredientDecorator&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Milk&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;IngredientDecorator&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;cost&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;beverage&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;cost&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;description&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;beverage&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;description&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;, Milk&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Mocha&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;IngredientDecorator&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;cost&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;beverage&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;cost&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;description&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;beverage&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;description&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;, Mocha&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Soy&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;IngredientDecorator&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;cost&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;beverage&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;cost&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;description&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;beverage&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;description&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;, Soy&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Chantilly&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;IngredientDecorator&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;cost&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;beverage&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;cost&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.25&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;description&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;beverage&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;description&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;, Chantilly&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Chocolate&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;IngredientDecorator&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;cost&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;beverage&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;cost&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0.30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;description&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;beverage&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;description&lt;/span&gt;() &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;, Chocolate&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;y su uso dentro de nuestro código sería&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;concrete_classes&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Coffee&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Decaf&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;HouseBlend&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;decorators&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Milk&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Mocha&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Soy&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Chantilly&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Chocolate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;if&lt;/span&gt; &lt;span style="color:#e06c75"&gt;__name__&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;==&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;chocolate_blend&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Chantilly&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Chocolate&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;HouseBlend&lt;/span&gt;()))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;soy_decaf&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Soy&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Decaf&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;moccachino&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Mocha&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Chocolate&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Milk&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Coffee&lt;/span&gt;())))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;chocolate_blend&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;cost&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;chocolate_blend&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;description&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;soy_decaf&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;cost&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;soy_decaf&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;description&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;moccachino&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;cost&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;moccachino&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;description&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;cuando ejecutemos este código podremos ver que en nuestro resultado obtendremos&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1.44
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;House Blend, Chocolate, Chantilly
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1.4
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Decaf, Soy
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2.59
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Coffee, Milk, Chocolate, Mocha
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="consideraciones-del-patrón-decorador"&gt;Consideraciones del patrón decorador&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;la herencia es una forma de extensión, pero no necesariamente la mejor forma de alcanzar la flexibilidad de nuestros diseños&lt;/li&gt;
&lt;li&gt;En nuestros diseños debemos de habilitar la extensión de nuevos comportamientos evitando la modificación del código actual&lt;/li&gt;
&lt;li&gt;la composición y la delegación pueden ser usados para agregar nuevos comportamientos en tiempo de ejecución&lt;/li&gt;
&lt;li&gt;El &lt;strong&gt;patrón decorador&lt;/strong&gt; provee una alternativa al uso de subclases para extender el comportamiento&lt;/li&gt;
&lt;li&gt;El &lt;strong&gt;patrón decorador&lt;/strong&gt; involucra el uso de clases decoradores que son usadas para encapsular componentes del mismo tipo en concreto&lt;/li&gt;
&lt;li&gt;Las clases decoradoras tienen el mismo tipo de la clase que decoran o encapsulan&lt;/li&gt;
&lt;li&gt;Los decoradores agregan nuevos comportamientos antes o después de que el objeto encapsulado realiza su trabajo&lt;/li&gt;
&lt;li&gt;Los decoradores normalmente son transparentes al cliente del componente&lt;/li&gt;
&lt;li&gt;Los decoradores pueden resultar en muchos objetos pequeños en nuestros diseños y el sobre uso del mismo puede derbar en crear código complejo y difícil de mantener&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Patrones de Diseño: Observador</title><link>https://blog.dacadev.com/programacion/patrones-de-diseno/observador/</link><pubDate>Mon, 08 Jan 2024 01:25:17 +0000</pubDate><guid>https://blog.dacadev.com/programacion/patrones-de-diseno/observador/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Explora el patrón observador, su implementación en Python y su aplicación en la vida real. Aprende sobre sus partes claves de implementación</description><media:content url="https://blog.dacadev.com/images/programming/design-patterns/observer/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#teoría"&gt;Teoría&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#implementación"&gt;Implementación&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#consideraciones-del-patrón-observador"&gt;*&lt;strong&gt;*Consideraciones del patrón observador**&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;El &lt;strong&gt;patrón observador&lt;/strong&gt; define una relación &lt;strong&gt;uno-a-muchos&lt;/strong&gt; entre objetos: cuando un objeto cambia de estado, todos sus dependientes son notificados automáticamente.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="teoría"&gt;Teoría&lt;/h2&gt;
&lt;p&gt;El &lt;strong&gt;patrón observador&lt;/strong&gt; es muy útil cuando se desea actualizar diversos objetos en función de los cambios en otros, siendo ampliamente implementado en frameworks frontend como React o Vue.&lt;/p&gt;
&lt;p&gt;Este patrón se basa en dos partes clave: los publishers u observables, que son los objetos emisores de valores, y los suscriptores, conocidos como observadores o subscribers. Estos últimos reciben los valores emitidos por los publishers.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;&lt;strong&gt;Publishers + Suscribers = Observer Pattern&lt;/strong&gt;&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;La esencia de este patrón es permitir que un &lt;strong&gt;&lt;code&gt;publisher&lt;/code&gt;&lt;/strong&gt; emita eventos a sus &lt;strong&gt;&lt;code&gt;subscribers&lt;/code&gt;&lt;/strong&gt;, teniendo además la capacidad de agregar o eliminar suscriptores de sus listas.&lt;/p&gt;
&lt;p&gt;Veamos gráficamente cómo funciona este patrón.&lt;/p&gt;




 
 
 
 &lt;div class="flex justify-center"&gt;
 &lt;img
 src="https://blog.dacadev.com/images/programming/design-patterns/observer/obvs_hu_55213fbec80361a.webp"
 alt="Imagen guia del contenido de la página"style="width:400px"/&gt;
 &lt;/div&gt;
 
 
 


&lt;p&gt;En el caso 1, observamos un Objeto &lt;strong&gt;Publisher&lt;/strong&gt; emitiendo valores constantemente, compartidos con todos los &lt;strong&gt;Suscribers&lt;/strong&gt; registrados en su lista. En este ejemplo, no hay suscriptores.&lt;/p&gt;
&lt;p&gt;En el caso 2, dos objetos están suscritos al objeto &lt;strong&gt;Publisher&lt;/strong&gt;, recibiendo el valor emitido en el momento de su emisión.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;El patrón &lt;strong&gt;Observer&lt;/strong&gt; permite relacionar objetos de manera comprensible, eficiente y mantenible. Es una relación &lt;strong&gt;One-to-Many&lt;/strong&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="implementación"&gt;Implementación&lt;/h2&gt;
&lt;p&gt;Implementaremos el patrón observer en Python definiendo dos clases abstractas: &lt;strong&gt;Publisher&lt;/strong&gt; y &lt;strong&gt;Subscriber&lt;/strong&gt;. Luego, crearemos clases derivadas que emitan valores (Publisher) y que se registren para recibir datos (Subscribers).&lt;/p&gt;
&lt;p&gt;Comenzamos con las clases abstractas:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;abc&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Suscriber&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;update&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;value&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;raise&lt;/span&gt; &lt;span style="color:#e06c75"&gt;NotImplementedError&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;You must implement this method&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Publisher&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;subscribers&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;Suscriber&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;add_suscriber&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;subscriber&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Suscriber&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;subscribers&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;append&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;subscriber&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;remove_suscriber&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;suscriber&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Suscriber&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;subscribers&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;remove&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;suscriber&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;notify_suscribers&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;value&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; &lt;span style="color:#e06c75"&gt;suscriber&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;in&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;subscribers&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En este código, definimos dos clases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Subscriber: Representa a los suscriptores o observadores, exigiendo la implementación del método &lt;strong&gt;&lt;code&gt;update&lt;/code&gt;&lt;/strong&gt;, que recibe el dato actualizado.&lt;/li&gt;
&lt;li&gt;Publisher: Define tres métodos clave: - &lt;strong&gt;add_subscriber&lt;/strong&gt;: Registra un nuevo suscriptor. - &lt;strong&gt;remove_subscriber&lt;/strong&gt;: Elimina un suscriptor específico. - &lt;strong&gt;notify_subscribers&lt;/strong&gt;: Actualiza el valor a todos los suscriptores.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Este código es una guía sobre cómo funciona el patrón y puede mejorarse según las necesidades de cada proyecto.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Ahora, implementemos este patrón en un ejemplo práctico: un sistema de IoT en casa que mide la radiación ultravioleta. Queremos compartir estos datos con dos sistemas: uno que almacena información para la protección infantil contra los rayos UV y otro para un sistema de riego basado en estas mediciones.&lt;/p&gt;
&lt;p&gt;Implementaremos tres clases:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;UVSolarSystem (Publisher)&lt;/li&gt;
&lt;li&gt;UVTracker (Suscriber)&lt;/li&gt;
&lt;li&gt;UVPlantTracker (Suscriber)&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;UVSolarSystem&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Publisher&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;emit_value&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;value&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;randint&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;0&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;100&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;notify_suscribers&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;value&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;UVTracker&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Suscriber&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;update&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;value&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;UVTracker: &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;value&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Doing funny stuff with this value :D&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;UVPlantTracker&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;Suscriber&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;update&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;value&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;UVPlantTracker: &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&lt;/span&gt;&lt;span style="color:#e06c75"&gt;value&lt;/span&gt;&lt;span style="color:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Doing funny stuff for the plants with this value :D&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En el código, el método &lt;strong&gt;&lt;code&gt;emit_value&lt;/code&gt;&lt;/strong&gt; en UVSolarSystem es personalizado y utiliza &lt;strong&gt;&lt;code&gt;notify_subscribers&lt;/code&gt;&lt;/strong&gt;. Las clases Subscriber implementan el método &lt;strong&gt;&lt;code&gt;update&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Probemos el código:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Stage 1&amp;#34;&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;center&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;50&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;=&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# define the publisher&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;solar_system&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UVSolarSystem&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;solar_system&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;emit_value&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Stage 2&amp;#34;&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;center&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;50&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;=&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# first suscriber&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;uv_tracker&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UVTracker&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;solar_system&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;add_suscriber&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;uv_tracker&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;solar_system&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;emit_value&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Stage 3&amp;#34;&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;center&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;50&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;=&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# second suscriber&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;uv_plant_tracker&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;UVPlantTracker&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;solar_system&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;add_suscriber&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;uv_plant_tracker&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;solar_system&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;emit_value&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Stage 4&amp;#34;&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;center&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;50&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;=&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# remove the first suscriber&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;solar_system&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;remove_suscriber&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;uv_tracker&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La salida sería&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; $ python main.py
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#56b6c2"&gt;=====================&lt;/span&gt;Stage &lt;span style="color:#e06c75"&gt;1&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;======================&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#56b6c2"&gt;=====================&lt;/span&gt;Stage &lt;span style="color:#e06c75"&gt;2&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;======================&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;UVTracker: &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Doing funny stuff with this value :D
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#56b6c2"&gt;=====================&lt;/span&gt;Stage &lt;span style="color:#e06c75"&gt;3&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;======================&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;UVTracker: &lt;span style="color:#d19a66"&gt;79&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Doing funny stuff with this value :D
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;UVPlantTracker: &lt;span style="color:#d19a66"&gt;79&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Doing funny stuff &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; the plants with this value :D
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#56b6c2"&gt;=====================&lt;/span&gt;Stage &lt;span style="color:#e06c75"&gt;4&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;======================&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;UVPlantTracker: &lt;span style="color:#d19a66"&gt;73&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Podemos mejorar el Publisher inicial agregando la posibilidad de retener el último valor emitido. Esto permite a los suscriptores acceder al valor cuando lo necesiten. El cambio en la clase &lt;strong&gt;&lt;code&gt;Publisher&lt;/code&gt;&lt;/strong&gt; sería:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;PublisherImprove&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;subscribers&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;Suscriber&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;_value&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;add_suscriber&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;subscriber&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Suscriber&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;subscribers&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;append&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;subscriber&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;remove_suscriber&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;suscriber&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Suscriber&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;subscribers&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;remove&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;suscriber&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;notify_suscribers&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; &lt;span style="color:#e06c75"&gt;suscriber&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;in&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;subscribers&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;suscriber&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;update&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;_value&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@property&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;get_value&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;_value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Agregamos el getter &lt;strong&gt;&lt;code&gt;get_value&lt;/code&gt;&lt;/strong&gt; para acceder al valor actual del Publisher, alojado como atributo privado &lt;strong&gt;&lt;code&gt;self._value&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="consideraciones-del-patrón-observador"&gt;*&lt;strong&gt;*Consideraciones del patrón observador**&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Define una relación one-to-many entre objetos.&lt;/li&gt;
&lt;li&gt;Los observables actualizan a los observadores a través de una interfaz común.&lt;/li&gt;
&lt;li&gt;Cualquier observador puede participar si cumple con la interfaz común.&lt;/li&gt;
&lt;li&gt;Los observadores deben estar desacoplados del observable.&lt;/li&gt;
&lt;li&gt;Es posible acceder a los datos del observable cuando sea necesario, en vez de esperar cada evento.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Patrones de Diseño: Estrategia</title><link>https://blog.dacadev.com/programacion/patrones-de-diseno/estrategia/</link><pubDate>Thu, 28 Dec 2023 01:25:17 +0000</pubDate><guid>https://blog.dacadev.com/programacion/patrones-de-diseno/estrategia/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Descubre cómo implementar el Patrón Estrategia en Python con un enfoque práctico en clases de aves, optimizando comportamientos flexibles en tiempo de ejecución</description><media:content url="https://blog.dacadev.com/images/programming/design-patterns/strategy/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;&lt;/nav&gt;
&lt;/details&gt;





 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;El &lt;strong&gt;patrón estrategia&lt;/strong&gt; define una familia de algoritmos intercambiables, encapsulando cada uno de ellos para que puedan ser usados de manera flexible en tiempo de ejecución.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Este patrón consiste en definir/identificar un conjunto de comportamientos comunes de un objeto y encapsular dichos comportamientos como una familia de algoritmos que, por definición, serán comunes entre ellos. De esta manera, si un objeto hace uso de dichos comportamientos, cada uno de ellos sería reemplazable por alguno de la misma familia.&lt;/p&gt;
&lt;p&gt;Apliquemos el concepto agnóstico y posteriormente lo aplicaremos en código.&lt;/p&gt;
&lt;p&gt;Supongamos que queremos crear un conjunto de clases que estén relacionadas con aves. Cada una de nuestras aves tendrá la capacidad de volar. Para aplicar el patrón estrategia, debemos identificar primero cuáles son esos comportamientos comunes que tienen nuestro conjunto de clases (Aves), para lo cual sería el método de volar, y vamos a encapsular este tipo de comportamiento. Esta idea se ilustra en el siguiente diagrama:&lt;/p&gt;
&lt;pre class="mermaid"&gt;classDiagram
 class Ave {
 +volar()
 }
 class NoVolar {
 ejecutarVuelo()
 }
 class SiVolar {
 ejecutarVuelo()
 }
 ComportamientoVolar &amp;lt;|-- NoVolar
 ComportamientoVolar &amp;lt;|-- SiVolar
 class ComportamientoVolar {
 +ejecutarVuelo()
 }
 Ave &amp;lt;|-- Pato
 Ave &amp;lt;|-- Gallina
 Ave --|&amp;gt; ComportamientoVolar
&lt;/pre&gt;

&lt;p&gt;Para este proceso optaremos por definir las clases abstractas de Aves y del comportamiento de volar, de esta manera podemos crear nuestras diversas clases y estas podrán emplear cualquiera de las clases que implementen la clase base de &lt;code&gt;comportamientoVolar&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Este código implementado en Python se vería de la siguiente manera:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;abc&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;abstractclassmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Clases abstractas&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;FlightBehavior&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@abstractclassmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;execute_fly&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Bird&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;flys_behavior&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;FlightBehavior&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;flys_behavior&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;flys_behavior&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;fly&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;flys_behavior&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;execute_fly&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Cómo utilizarlo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# 1. Definir las clases que implementan las clases abstractas&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Estrategias&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;NoFly&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;FlightBehavior&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;super&lt;/span&gt;()&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;execute_fly&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;I can&amp;#39;t fly&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Fly&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;FlightBehavior&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;super&lt;/span&gt;()&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;execute_fly&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;I can fly&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Clases que implementan la estrategia&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Hen&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Bird&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;flys_behavior&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;FlightBehavior&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;super&lt;/span&gt;()&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;flys_behavior&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e06c75"&gt;flys_behavior&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Duck&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Bird&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;flys_behavior&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;FlightBehavior&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;super&lt;/span&gt;()&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;flys_behavior&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#e06c75"&gt;flys_behavior&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# 2. Crear los objetos&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;if&lt;/span&gt; &lt;span style="color:#e06c75"&gt;__name__&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;==&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;hen&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Hen&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;NoFly&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;hen&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;fly&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;duck&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Duck&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Fly&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;duck&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;fly&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Este patrón es útil en situaciones en las que tienes una clase que tiene varios comportamientos y quieres que el comportamiento se seleccione en tiempo de ejecución, según las necesidades de tu aplicación. Por ejemplo, puedes tener una clase que realiza operaciones matemáticas y quieres poder cambiar la operación que realiza en tiempo de ejecución, según las necesidades de la aplicación.&lt;/p&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;El patrón estrategia es ideal cuando tienes múltiples algoritmos para una tarea y necesitas cambiar entre ellos de forma dinámica. Piensa en sistemas de pago, algoritmos de ordenamiento o validaciones configurables.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;A continuación, un ejemplo de Python de este caso de cambio de estrategia en tiempo de ejecución:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;from&lt;/span&gt; &lt;span style="color:#e06c75"&gt;abc&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Context&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__init__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;strategy&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#39;Strategy&amp;#39;&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;_strategy&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;strategy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;execute_strategy&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;x&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;y&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;_strategy&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;execute&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;x&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;y&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;Strategy&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;ABC&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#61afef"&gt;@abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;execute&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;x&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;y&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;AddStrategy&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Strategy&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;execute&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;x&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;y&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;x&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;class&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;SubtractStrategy&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;Strategy&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;execute&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;x&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;y&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;x&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;-&lt;/span&gt; &lt;span style="color:#e06c75"&gt;y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;# Uso de las clases&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;context&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Context&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;AddStrategy&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;context&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;execute_strategy&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;10&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;5&lt;/span&gt;)) &lt;span style="color:#7f848e"&gt;# Salida: 15&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;context&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Context&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;SubtractStrategy&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;context&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;execute_strategy&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;10&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;5&lt;/span&gt;)) &lt;span style="color:#7f848e"&gt;# Salida: 5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title>Patrones de diseño: Qué son?</title><link>https://blog.dacadev.com/programacion/patrones-de-diseno/que-son/</link><pubDate>Sat, 02 Dec 2023 00:29:10 +0000</pubDate><guid>https://blog.dacadev.com/programacion/patrones-de-diseno/que-son/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Descubre los patrones de diseño en programación: soluciones clave para retos de software, categorías principales y principios para desarrolladores</description><media:content url="https://blog.dacadev.com/images/programming/design-patterns/what-is/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#principios-de-diseño"&gt;Principios de diseño&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#qué-no-hacer-al-usar-patrones-de-diseño"&gt;Qué No Hacer al Usar Patrones de Diseño&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Los patrones de diseño, en general, se pueden definir como soluciones estandarizadas a problemas comunes en el diseño de software. No son fragmentos de código específicos, sino más bien guías o plantillas que se pueden aplicar en diversos contextos de programación.&lt;/p&gt;
&lt;p&gt;Estos patrones son especialmente útiles porque permiten reutilizar conocimientos y enfoques que han sido probados y perfeccionados a lo largo de los años, y proporcionan un punto de partida para tus proyectos de software.&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;Los patrones de diseño son guías que pueden ser adaptadas para cada propósito específico según se requiera.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Los patrones de diseño se dividen en tres categorías principales:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Patrones Creacionales:&lt;/strong&gt; Estos patrones se relacionan con los procesos de creación de objetos. Su objetivo es abstraer los detalles de la instanciación de clases, haciendo los sistemas más independientes de cómo sus objetos son creados y representados. Dentro de esta categoría encontramos los patrones:
&lt;ul&gt;
&lt;li&gt;Singleton&lt;/li&gt;
&lt;li&gt;Factory Method&lt;/li&gt;
&lt;li&gt;Abstract Factory&lt;/li&gt;
&lt;li&gt;Builder&lt;/li&gt;
&lt;li&gt;Prototype.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Patrones Estructurales:&lt;/strong&gt; Estos patrones se enfocan en cómo las clases y objetos se componen para formar estructuras más grandes. Los patrones estructurales facilitan el diseño al identificar formas sencillas de realizar relaciones entre entidades. Dentro de esta categoría encontramos los patrones:
&lt;ul&gt;
&lt;li&gt;Adapter&lt;/li&gt;
&lt;li&gt;Bridge&lt;/li&gt;
&lt;li&gt;Composite&lt;/li&gt;
&lt;li&gt;Decorator&lt;/li&gt;
&lt;li&gt;Facade&lt;/li&gt;
&lt;li&gt;Flyweight&lt;/li&gt;
&lt;li&gt;Proxy.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Patrones de Comportamiento:&lt;/strong&gt; Estos patrones se centran en la comunicación entre objetos. Son útiles para definir patrones de comunicación entre clases y objetos, haciéndolos más flexibles y eficientes. Encontraremos patrones como:
&lt;ul&gt;
&lt;li&gt;Observer [&lt;a href="https://blog.dacadev.com/programacion/patrones-de-diseno/observador"



 


&gt;&lt;strong&gt;más info&lt;/strong&gt;&lt;/a&gt;]&lt;/li&gt;
&lt;li&gt;Mediator&lt;/li&gt;
&lt;li&gt;Iterator&lt;/li&gt;
&lt;li&gt;Strategy [&lt;a href="https://blog.dacadev.com/programacion/patrones-de-diseno/estrategia"



 


&gt;&lt;strong&gt;más info&lt;/strong&gt;&lt;/a&gt;]&lt;/li&gt;
&lt;li&gt;Command&lt;/li&gt;
&lt;li&gt;State&lt;/li&gt;
&lt;li&gt;Visitor.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cada patrón tiene su propio conjunto de reglas y contextos donde es más adecuado. Lo importante es entender que no existe un patrón que sea mejor que los otros en todas las situaciones.&lt;/p&gt;
&lt;h2 id="principios-de-diseño"&gt;Principios de diseño&lt;/h2&gt;
&lt;p&gt;Antes de adentrarte en los patrones de diseño, es buena idea tener unas bases y conceptos iniciales que te ayudarán al momento de estudiar cada uno de los patrones. Estos principios son:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Identifica los aspectos de tu aplicación que pueden cambiar y sepáralos de aquellos que probablemente seguirán igual.&lt;/li&gt;
&lt;li&gt;Programa para una interfaz, no para una implementación. Programar para interfaces significa programar para supertipos.&lt;/li&gt;
&lt;li&gt;Prefiere la composición sobre la herencia en OO. Es decir, si debes escoger entre una u otra, es más flexible y fácil implementar la composición, ya que esta se define a través de interfaces.&lt;/li&gt;
&lt;li&gt;Esfuérzate por lograr diseños con acoplamientos débiles entre objetos que interactúan. Es decir, disminuye al máximo la dependencia entre los objetos de tu aplicación.&lt;/li&gt;
&lt;li&gt;Las clases deben ser abiertas a código nuevo y cerradas a la modificación del mismo. Es decir, se debe evitar modificar lo existente siempre que sea posible.&lt;/li&gt;
&lt;li&gt;Depende de abstracciones, no de clases concretas. Es decir, no utilices una clase como dependencia de otra; en su lugar, usa una clase abstracta o una interfaz&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="qué-no-hacer-al-usar-patrones-de-diseño"&gt;Qué No Hacer al Usar Patrones de Diseño&lt;/h2&gt;
&lt;p&gt;Al momento de estudiar y trabajar con los patrones de diseño, es importante tener en cuenta los siguientes puntos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Conocer las bases de Orientación a Objetos (OO) no te hace un buen diseñador de OO.&lt;/li&gt;
&lt;li&gt;Un buen diseño de OO es reutilizable, extensible y mantenible a lo largo del tiempo.&lt;/li&gt;
&lt;li&gt;Los patrones te muestran cómo construir buenos sistemas usando cualidades de OO.&lt;/li&gt;
&lt;li&gt;Los patrones son experiencias probadas orientadas a objetos.&lt;/li&gt;
&lt;li&gt;Los patrones no te dan código; ellos te dan una solución general a problemas de diseño. Tu objetivo como programador e ingeniero de Software es aplicarlos y adaptarlos a tus casos específicos.&lt;/li&gt;
&lt;li&gt;Los patrones no son inventados, son descubiertos. Tú podrías encontrar otro a lo largo de tu carrera.&lt;/li&gt;
&lt;li&gt;La mayoría de los patrones y principios son capaces de manejar el constante cambio en el software, permitiéndote adaptar tu código a nuevos requerimientos sin grandes refactorizaciones.&lt;/li&gt;
&lt;/ul&gt;




 
 





 


&lt;div class="notice tip"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="22" height="22"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" /&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Tip&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;No intentes aplicar todos los patrones de una vez. Empieza por entender el problema que resuelve cada uno y úsalos cuando el contexto lo requiera. La sobreingeniería es tan perjudicial como la falta de diseño.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>Código Limpio: Escribe nombres significativos</title><link>https://blog.dacadev.com/programacion/codigo-limpio/nombres-significativos/</link><pubDate>Thu, 14 Sep 2023 02:18:24 +0000</pubDate><guid>https://blog.dacadev.com/programacion/codigo-limpio/nombres-significativos/</guid><dc:creator>Dacadev</dc:creator><category>programación</category><description>Aprende a nombrar variables y funciones eficazmente con consejos de 'Código Limpio'. Mejora la legibilidad y mantenimiento de tu código.</description><media:content url="https://blog.dacadev.com/images/programming/clean-code/meaning-names/banner.png" medium="image" type="image/png"/><content:encoded>
&lt;details class="table-of-content "&gt;
 &lt;summary&gt;
 
 Tabla de Contenido
 
 &lt;/summary&gt;
 &lt;nav id="TableOfContents"&gt;
 &lt;ol&gt;
 &lt;li&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#nombres-significativos"&gt;Nombres significativos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#transmitir-el-propósito-del-código"&gt;Transmitir el propósito del código&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#sé-explícito-y-puntual"&gt;Sé explícito y puntual&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#variables-similares"&gt;Variables similares&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#nombres-pronunciables"&gt;Nombres pronunciables&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#nombres-fáciles-de-buscar"&gt;Nombres fáciles de buscar&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#no-permitas-los-mapas-mentales"&gt;No permitas los mapas mentales&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#nombres-en-las-clases"&gt;Nombres en las clases&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Al momento de escribir código, una tarea difícil de la que nadie habla es el hecho de nombrar nuestras variables, funciones, clases, etc. Y si no lo sientes así, déjame contarte por qué es algo a lo que deberías prestarle atención 😉.&lt;/p&gt;
&lt;p&gt;Te voy a compartir algunos consejos que te ayudarán a la hora de definir dichos nombres y el porqué es buena práctica. Dentro de estos consejos encontramos&amp;hellip;&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 El contenido de este post está basado en las enseñanzas del libro &amp;ldquo;Código Limpio&amp;rdquo; y lo que he aprendido a lo largo de mi carrera como programador.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id="nombres-significativos"&gt;Nombres significativos&lt;/h3&gt;
&lt;p&gt;Los nombres deben transmitir claramente cuál es el propósito del código, es decir, que con el hecho de leer la variable o función, se debe entender qué contiene.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Incorrecto
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;[] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Correcto
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;users&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;[] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En el ejemplo anterior podemos ver que en la primera parte estamos definiendo nombres aleatorios para nuestro código lo cual no nos dice nada y en dado caso debemos leer más a fondo el código para entender qué es lo que hace, mientras que en la segunda parte podemos ver claramente que la variable será un arreglo de usuarios.&lt;/p&gt;
&lt;h3 id="transmitir-el-propósito-del-código"&gt;Transmitir el propósito del código&lt;/h3&gt;
&lt;p&gt;Los nombres deben transmitir claramente cuál es la intención o uso del código. Por ejemplo, en el siguiente ejemplo podemos ver que en la primera parte el nombre no nos dice nada sobre lo que hace la función, mientras que en la segunda parte podemos ver que el nombre nos dice claramente que dicha función escribirá &lt;code&gt;Hello World&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Incorrecto
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;foo&lt;/span&gt;()&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Hello World&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Correcto
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;printHelloWorld&lt;/span&gt;()&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;console&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;log&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;Hello World&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 Incluso podemos mejorar el nombre de la función &lt;code&gt;printHelloWorld&lt;/code&gt; a &lt;code&gt;printHelloWorldToConsole&lt;/code&gt; para ser más explícitos.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id="sé-explícito-y-puntual"&gt;Sé explícito y puntual&lt;/h3&gt;
&lt;p&gt;Los nombres que des dentro de tu código deben ser explícitos, esto significa que deben ser claros al transmitir información, esto ya lo mencioné, pero no caigas en hacerlo en exceso. Observa el siguiente ejemplo.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Incorrecto
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;usersStringNameArray&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;[] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#34;John&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;Mary&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;Sam&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Correcto
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;const&lt;/span&gt; &lt;span style="color:#e06c75"&gt;userNames&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;[] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; [&lt;span style="color:#98c379"&gt;&amp;#34;John&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;Mary&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;Sam&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En el ejemplo observamos que estamos repitiendo información que ya nos brinda el tipado, como por ejemplo nombrar que es un arreglo de &lt;code&gt;strings&lt;/code&gt;, lo que termina siendo redundante ya que el tipo de dato está implícito en el tipado &lt;code&gt;string[]&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="variables-similares"&gt;Variables similares&lt;/h3&gt;
&lt;p&gt;Habrá casos en donde tengas variables cuyo comportamiento es similar o que hagan referencia a un mismo valor y puede ser difícil nombrarlas. Usa nombres que realmente distingan la funcionalidad de dicha variable y cuál es su objetivo, como en el siguiente código:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Incorrecto
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;copyChars&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;a1&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;[], &lt;span style="color:#e06c75"&gt;a2&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;[])&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; (&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;i&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;; &lt;span style="color:#e06c75"&gt;i&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a1&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;length&lt;/span&gt;; &lt;span style="color:#e06c75"&gt;i&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;a2&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;i&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;a1&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;i&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#7f848e"&gt;// Correcto
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;function&lt;/span&gt; &lt;span style="color:#e06c75"&gt;copyChars&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;source&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;[], &lt;span style="color:#e06c75"&gt;destination&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;string&lt;/span&gt;[])&lt;span style="color:#56b6c2"&gt;:&lt;/span&gt; &lt;span style="color:#c678dd"&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; (&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;i&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;; &lt;span style="color:#e06c75"&gt;i&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;source&lt;/span&gt;.&lt;span style="color:#e06c75"&gt;length&lt;/span&gt;; &lt;span style="color:#e06c75"&gt;i&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;destination&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;i&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;source&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;i&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Para el ejemplo anterior, podemos observar que el uso de &lt;code&gt;source&lt;/code&gt; y &lt;code&gt;destination&lt;/code&gt; en lugar de &lt;code&gt;a1&lt;/code&gt; y &lt;code&gt;a2&lt;/code&gt; transmite claramente la funcionalidad de cada variable a pesar de ser similares.&lt;/p&gt;
&lt;h3 id="nombres-pronunciables"&gt;Nombres pronunciables&lt;/h3&gt;
&lt;p&gt;Usa nombres que sean pronunciables y que estén relacionados con el lenguaje que se esté usando al momento de escribir código. De esta manera, al leer el código no tendrás que hacer mapas mentales de los nombres.&lt;/p&gt;
&lt;h3 id="nombres-fáciles-de-buscar"&gt;Nombres fáciles de buscar&lt;/h3&gt;
&lt;p&gt;En concordancia con el punto anterior, además de tener nombres pronunciables, también piensa en que sean fáciles de buscar dentro del código o incluso dentro del proyecto.&lt;/p&gt;
&lt;p&gt;Intenta evitar el uso de variables sencillas como a, además de que no transmiten nada, encontrarlas es difícil. ¿Cuántas palabras no tienen una &amp;lsquo;a&amp;rsquo;? 🙃&lt;/p&gt;




 
 





 


&lt;div class="notice note"&gt;
 &lt;div class="notice-head"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" width="22" height="22" stroke-width="1.5" stroke="currentColor"&gt;
 &lt;path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" /&gt;
 &lt;/svg&gt;
 &lt;p&gt;Note&lt;/p&gt;
 
 &lt;/div&gt;
 &lt;div class="notice-body"&gt;&lt;p&gt;🚀 Solo en casos en donde la variable se use una vez en códigos pequeños, como ciclos &lt;code&gt;for&lt;/code&gt;, podemos optar por usar variables simples como &lt;code&gt;e&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#c678dd"&gt;for&lt;/span&gt; (&lt;span style="color:#c678dd"&gt;let&lt;/span&gt; &lt;span style="color:#e06c75"&gt;j&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;number&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;0&lt;/span&gt;; &lt;span style="color:#e06c75"&gt;j&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#d19a66"&gt;34&lt;/span&gt;; &lt;span style="color:#e06c75"&gt;j&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;s&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+=&lt;/span&gt; (&lt;span style="color:#e06c75"&gt;t&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;j&lt;/span&gt;] &lt;span style="color:#56b6c2"&gt;*&lt;/span&gt; &lt;span style="color:#d19a66"&gt;4&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;/&lt;/span&gt; &lt;span style="color:#d19a66"&gt;5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="no-permitas-los-mapas-mentales"&gt;No permitas los mapas mentales&lt;/h3&gt;
&lt;p&gt;Cuando nos referimos a mapas mentales del código, estamos pensando en los demás (inclusive en tu yo del futuro). Cuando estás leyendo código y empiezas a crear mapas en tu cabeza con las relaciones de cada nombre de variable, función, etc., estás agregando una tarea adicional e innecesaria porque en sí tienes que entender el código y ahora tener ese mapa de nombres en la cabeza. ¿Imagínate si tienes muchas variables o nombres?&lt;/p&gt;
&lt;p&gt;Para evitar esto, no uses nombres simples como &lt;code&gt;i&lt;/code&gt;, &lt;code&gt;j&lt;/code&gt; (muy común en ciclos for) o &lt;code&gt;r&lt;/code&gt; para decir &lt;code&gt;url&lt;/code&gt; o &lt;code&gt;response&lt;/code&gt;. Simplemente coloca el nombre que corresponde.&lt;/p&gt;
&lt;h3 id="nombres-en-las-clases"&gt;Nombres en las clases&lt;/h3&gt;
&lt;p&gt;Además de los consejos ya presentados, en las clases debemos tener en cuenta también otros casos para escribir código entendible y mantenible. Ten en cuenta estas consideraciones:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Las clases deben tener nombres sustantivos y NO verbales o de acciones. Un sustantivo es una palabra que se utiliza para nombrar personas, animales, cosas, lugares o ideas.&lt;/li&gt;
&lt;li&gt;Los métodos de las clases deben tener nombres que hagan referencia a verbos o frases verbales, como &lt;code&gt;postPayment&lt;/code&gt;, &lt;code&gt;deletePage&lt;/code&gt; o &lt;code&gt;save&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Los accesores, mutadores, getters o setters deben ser nombrados según su valor y llevar el prefijo &lt;code&gt;get/set&lt;/code&gt; e &lt;code&gt;is&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Define una forma de nombrar las acciones y aférrate a ella. Por ejemplo, si usas get, no uses &lt;code&gt;fetch&lt;/code&gt; en otros. De esta manera mantienes la consistencia a través del código y/o proyecto.&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item></channel></rss>