<?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>Tipado en Python · DacaCode &lt;/&gt;</title><link>https://blog.dacadev.com/series/tipado-en-python/</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>Tue, 13 Aug 2024 00:00:00 -0500</lastBuildDate><atom:link href="https://blog.dacadev.com/series/tipado-en-python/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>Tipado en Python: Estructuras de datos</title><link>https://blog.dacadev.com/python/tipado/estructuras-de-datos/</link><pubDate>Tue, 13 Aug 2024 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/python/tipado/estructuras-de-datos/</guid><dc:creator>Dacadev</dc:creator><category>python</category><description>Aprende a elegir estructuras de datos tipadas en Python con TypedDict, NotRequired, Required y dataclass para modelos claros.</description><media:content url="https://blog.dacadev.com/images/python/typing/data-structures/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="#diccionarios-tipados-en-python"&gt;Diccionarios tipados en Python&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#typeddict-diccionarios-con-forma-definida"&gt;TypedDict: diccionarios con forma definida&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#llaves-opcionales-con-notrequired"&gt;Llaves opcionales con NotRequired&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#enfoque-inverso-totalfalse-y-required"&gt;Enfoque inverso: total=False y Required&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#dataclass-estructuras-de-datos-con-atributos"&gt;Dataclass: estructuras de datos con atributos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#dataclass-vs-class-tradicional"&gt;Dataclass vs class tradicional&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#cuándo-usar-cada-estructura-de-datos"&gt;Cuándo usar cada estructura de datos&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#cierre"&gt;Cierre&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Cuando una función recibe datos de un producto, un usuario o una respuesta de una API, el problema no suele ser solamente el tipo de cada valor, sino la forma completa del objeto. Las &lt;strong&gt;estructuras de datos tipadas en Python&lt;/strong&gt; nos permiten documentar y validar mejor esa forma: qué claves existen, cuáles son opcionales y cuándo conviene pasar de un diccionario a una estructura con comportamiento propio.&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;Este artículo es parte de una serie que explica 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;p&gt;En artículos anteriores vimos cómo agregar tipos a variables, colecciones y funciones. Ahora vamos a llevar esa idea a estructuras que representan datos con significado dentro de una aplicación: productos, órdenes, usuarios, configuraciones o payloads de entrada/salida.&lt;/p&gt;
&lt;h2 id="diccionarios-tipados-en-python"&gt;Diccionarios tipados en Python&lt;/h2&gt;
&lt;p&gt;Los diccionarios son una de las formas más comunes de representar datos en Python. Nos permiten asociar llaves con valores, y esas llaves deben ser objetos hashables, normalmente &lt;code&gt;str&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt; o tuplas inmutables.&lt;/p&gt;
&lt;p&gt;Para agregar tipado a un diccionario podemos usar &lt;code&gt;dict[&amp;lt;tipo_llave&amp;gt;, &amp;lt;tipo_valor&amp;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-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;product&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;dict&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&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:#e5c07b"&gt;int&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;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;Camisa&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;&amp;#34;price&amp;#34;&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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En este ejemplo estamos indicando que las llaves son &lt;code&gt;str&lt;/code&gt; y que los valores pueden ser &lt;code&gt;str&lt;/code&gt; o &lt;code&gt;int&lt;/code&gt;. Esto ayuda a evitar errores como usar una llave de tipo incorrecto o asignar un valor fuera del rango esperado.&lt;/p&gt;
&lt;p&gt;Sin embargo, esta aproximación tiene una limitación importante: &lt;strong&gt;no transmite qué claves se esperan&lt;/strong&gt; dentro del diccionario. El analizador estático sabe que puede existir cualquier llave &lt;code&gt;str&lt;/code&gt;, pero no sabe que esperamos exactamente &lt;code&gt;name&lt;/code&gt; y &lt;code&gt;price&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:#e06c75"&gt;product&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;dict&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&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:#e5c07b"&gt;int&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;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;Camisa&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;&amp;#34;price&amp;#34;&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&gt;&lt;/span&gt;&lt;span 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;product&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;# ✅ válido&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;product&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;category&amp;#34;&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;# ✅ también parece válido para el type checker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El segundo acceso puede fallar en tiempo de ejecución con un &lt;code&gt;KeyError&lt;/code&gt;, pero el tipo &lt;code&gt;dict[str, str | int]&lt;/code&gt; no expresa que &lt;code&gt;category&lt;/code&gt; no hace parte del contrato de esa estructura.&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;Un diccionario tipado con &lt;code&gt;dict[str, ...]&lt;/code&gt; es útil cuando trabajas con pares clave-valor homogéneos o dinámicos. Cuando necesitas describir una forma específica de datos, conviene usar &lt;code&gt;TypedDict&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="typeddict-diccionarios-con-forma-definida"&gt;TypedDict: diccionarios con forma definida&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;TypedDict&lt;/code&gt;, disponible desde el módulo &lt;a href="https://docs.python.org/3/library/typing.html#typing.TypedDict"




 target="_blank"
 


&gt;&lt;code&gt;typing&lt;/code&gt;&lt;/a&gt;, nos permite definir un diccionario con claves conocidas y valores tipados. Es especialmente útil para payloads JSON, respuestas de APIs o datos que siguen siendo diccionarios, pero tienen una estructura clara.&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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;TypedDict&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;Product&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;TypedDict&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;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;price&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;tags&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&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:#e06c75"&gt;active&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&gt;&lt;/span&gt;&lt;span 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;product&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Product&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;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;Camisa&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;&amp;#34;price&amp;#34;&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:#98c379"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;: [&lt;span style="color:#98c379"&gt;&amp;#34;ropa&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;&amp;#34;active&amp;#34;&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;Con esta definición, el type checker entiende que &lt;code&gt;Product&lt;/code&gt; debe tener las claves &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;price&lt;/code&gt;, &lt;code&gt;tags&lt;/code&gt; y &lt;code&gt;active&lt;/code&gt;, y que cada una espera un tipo específico.&lt;/p&gt;
&lt;p&gt;Es importante recordar que &lt;code&gt;TypedDict&lt;/code&gt; &lt;strong&gt;no cambia el comportamiento del diccionario en tiempo de ejecución&lt;/strong&gt;. Seguimos trabajando con un &lt;code&gt;dict&lt;/code&gt;, no con una clase tradicional.&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;product&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;# ✅ funciona&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;product&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:#7f848e"&gt;# ❌ no funciona&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;TypedDict&lt;/code&gt; mejora la información disponible para herramientas como editores, linters y analizadores estáticos. Pero el acceso sigue siendo por llave, igual que en cualquier diccionario.&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;No uses &lt;code&gt;TypedDict&lt;/code&gt; esperando validación automática en tiempo de ejecución. Su objetivo principal es mejorar el tipado estático y la documentación del contrato de datos.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="llaves-opcionales-con-notrequired"&gt;Llaves opcionales con NotRequired&lt;/h2&gt;
&lt;p&gt;En muchos casos una estructura tiene campos obligatorios y campos opcionales. Por ejemplo, un producto puede requerir &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;price&lt;/code&gt; y &lt;code&gt;active&lt;/code&gt;, pero permitir que &lt;code&gt;tags&lt;/code&gt; no exista.&lt;/p&gt;
&lt;p&gt;Para ese caso podemos usar &lt;code&gt;NotRequired&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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;NotRequired&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;TypedDict&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;Product&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;TypedDict&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;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;price&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;tags&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;NotRequired&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;list&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:#e06c75"&gt;active&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&gt;&lt;/span&gt;&lt;span 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;product_without_tags&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Product&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;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;Camisa&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;&amp;#34;price&amp;#34;&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:#98c379"&gt;&amp;#34;active&amp;#34;&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;La clave &lt;code&gt;tags&lt;/code&gt; ahora puede omitirse. Esto es diferente a decir que &lt;code&gt;tags&lt;/code&gt; puede ser &lt;code&gt;None&lt;/code&gt;. Con &lt;code&gt;NotRequired[list[str]]&lt;/code&gt;, la llave completa puede no existir.&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;Product&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;TypedDict&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;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;tags&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;NotRequired&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;list&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&gt;&lt;/span&gt;&lt;span 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;product&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Product&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; {&lt;span style="color:#98c379"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;Camisa&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;product&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;#34;tags&amp;#34;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# ✅ acceso seguro si la llave puede no existir&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;product&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;# ⚠️ puede lanzar KeyError en tiempo de ejecución&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;Si una llave es opcional, usa &lt;code&gt;get()&lt;/code&gt; o valida su existencia antes de acceder con &lt;code&gt;[]&lt;/code&gt;. El tipado te ayuda a diseñar el contrato, pero no elimina los errores de acceso en tiempo de ejecución.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="enfoque-inverso-totalfalse-y-required"&gt;Enfoque inverso: total=False y Required&lt;/h2&gt;
&lt;p&gt;También podemos definir el caso contrario: que todas las llaves sean opcionales por defecto y marcar únicamente algunas como obligatorias. Para ello usamos &lt;code&gt;total=False&lt;/code&gt; junto con &lt;code&gt;Required&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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Required&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;TypedDict&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;Product&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;TypedDict&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;total&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;name&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Required&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:#e06c75"&gt;price&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Required&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;tags&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&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:#e06c75"&gt;active&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&gt;&lt;/span&gt;&lt;span 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;product&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Product&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;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;Camisa&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;&amp;#34;price&amp;#34;&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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Aquí &lt;code&gt;name&lt;/code&gt; y &lt;code&gt;price&lt;/code&gt; son obligatorias, mientras que &lt;code&gt;tags&lt;/code&gt; y &lt;code&gt;active&lt;/code&gt; pueden omitirse. Este enfoque es útil cuando la mayoría de campos son opcionales y solo necesitas destacar unos pocos como requeridos.&lt;/p&gt;
&lt;p&gt;La decisión entre &lt;code&gt;NotRequired&lt;/code&gt; y &lt;code&gt;total=False + Required&lt;/code&gt; depende de la forma dominante de tu estructura:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Usa &lt;code&gt;NotRequired&lt;/code&gt; cuando la mayoría de campos son obligatorios.&lt;/li&gt;
&lt;li&gt;Usa &lt;code&gt;total=False + Required&lt;/code&gt; cuando la mayoría de campos son opcionales.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dataclass-estructuras-de-datos-con-atributos"&gt;Dataclass: estructuras de datos con atributos&lt;/h2&gt;
&lt;p&gt;Una &lt;a href="https://docs.python.org/3/library/dataclasses.html"




 target="_blank"
 


&gt;&lt;code&gt;dataclass&lt;/code&gt;&lt;/a&gt; es una clase diseñada para almacenar datos con menos código repetitivo. Python agregó este decorador en la versión 3.7, y desde entonces se convirtió en una herramienta muy práctica para modelar objetos de datos.&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;dataclasses&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;dataclass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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:#61afef"&gt;@dataclass&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;Product&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;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;price&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;active&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:#e06c75"&gt;tags&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&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&gt;&lt;/span&gt;&lt;span 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;product&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Product&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;Camisa&amp;#34;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;price&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;20&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;active&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:#e06c75"&gt;tags&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;ropa&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;product&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 style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;product&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;price&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A diferencia de &lt;code&gt;TypedDict&lt;/code&gt;, aquí sí accedemos a los datos como atributos: &lt;code&gt;product.name&lt;/code&gt;, &lt;code&gt;product.price&lt;/code&gt;, &lt;code&gt;product.tags&lt;/code&gt;. Además, &lt;code&gt;dataclass&lt;/code&gt; genera automáticamente métodos como &lt;code&gt;__init__&lt;/code&gt;, &lt;code&gt;__repr__&lt;/code&gt; y &lt;code&gt;__eq__&lt;/code&gt;, lo que reduce la cantidad de código necesario.&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;product_1&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Product&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;Camisa&amp;#34;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;price&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;20&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;active&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:#e06c75"&gt;tags&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;ropa&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;product_2&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Product&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;Camisa&amp;#34;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;price&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;20&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;active&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:#e06c75"&gt;tags&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;ropa&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;product_1&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;==&lt;/span&gt; &lt;span style="color:#e06c75"&gt;product_2&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:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;product_1&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# Product(name=&amp;#39;Camisa&amp;#39;, price=20, active=True, tags=[&amp;#39;ropa&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;&lt;code&gt;dataclass&lt;/code&gt; sigue siendo una clase de Python. El decorador solo genera código común por ti, sin impedir que agregues métodos, validaciones o comportamiento adicional cuando lo necesites.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="dataclass-vs-class-tradicional"&gt;Dataclass vs class tradicional&lt;/h2&gt;
&lt;p&gt;Podemos escribir una clase tradicional para representar el mismo producto:&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;Product&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&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&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;str&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;price&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;active&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:#e06c75"&gt;tags&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&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:#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;name&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 style="color:#e5c07b"&gt;self&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;price&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;price&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;active&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;active&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;tags&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;tags&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El código funciona, pero gran parte de la implementación es repetitiva. Solo estamos recibiendo argumentos y asignándolos como atributos. Con &lt;code&gt;dataclass&lt;/code&gt;, expresamos la misma estructura de forma más directa:&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;dataclasses&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;dataclass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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:#61afef"&gt;@dataclass&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;Product&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;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;price&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;active&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:#e06c75"&gt;tags&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La diferencia no es solamente estética. &lt;code&gt;dataclass&lt;/code&gt; comunica intención: esta clase existe principalmente para alojar datos. Además, mantiene una buena integración con type hints y reduce el riesgo de inconsistencias entre los argumentos de &lt;code&gt;__init__&lt;/code&gt; y los atributos reales.&lt;/p&gt;
&lt;p&gt;También puedes agregar comportamiento cuando haga falta:&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;dataclasses&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;dataclass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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:#61afef"&gt;@dataclass&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;Product&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;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;price&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;active&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:#e06c75"&gt;tags&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&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&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;has_tag&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;tag&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;bool&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;tag&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;tags&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;product&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Product&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;Camisa&amp;#34;&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;price&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#d19a66"&gt;20&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;active&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:#e06c75"&gt;tags&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;ropa&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;product&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;has_tag&lt;/span&gt;(&lt;span style="color:#98c379"&gt;&amp;#34;ropa&amp;#34;&lt;/span&gt;)) &lt;span style="color:#7f848e"&gt;# True&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;Si tu clase solo define &lt;code&gt;__init__&lt;/code&gt;, &lt;code&gt;__repr__&lt;/code&gt; o comparaciones básicas para alojar datos, probablemente una &lt;code&gt;dataclass&lt;/code&gt; expresa mejor la intención.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="cuándo-usar-cada-estructura-de-datos"&gt;Cuándo usar cada estructura de datos&lt;/h2&gt;
&lt;p&gt;No existe una única estructura correcta para todos los casos. La decisión depende de si estás modelando datos dinámicos, contratos de intercambio o entidades con comportamiento.&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
 A[Necesitas representar datos con estructura] --&amp;gt; B{¿Debe seguir siendo un dict?}
 B -- Sí --&amp;gt; C{¿Conoces las claves esperadas?}
 C -- No --&amp;gt; D[&amp;#34;Usa dict[str, tipo]&amp;#34;]
 C -- Sí --&amp;gt; E[Usa TypedDict]
 B -- No --&amp;gt; F{¿Principalmente almacena datos?}
 F -- Sí --&amp;gt; G[Usa dataclass]
 F -- No --&amp;gt; H[Usa class tradicional]
&lt;/pre&gt;

&lt;p&gt;Como regla práctica:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;dict[str, tipo]&lt;/code&gt;&lt;/strong&gt;: úsalo cuando las claves son dinámicas o la estructura es homogénea. Por ejemplo, contadores, mapas de configuración simples o agrupaciones donde todas las llaves comparten el mismo tipo de valor.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;TypedDict&lt;/code&gt;&lt;/strong&gt;: úsalo cuando necesitas conservar el comportamiento de diccionario, pero quieres describir claves específicas. Es una buena opción para JSON, payloads de APIs y datos serializables.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;dataclass&lt;/code&gt;&lt;/strong&gt;: úsala cuando quieres representar datos con atributos, comparación automática y una intención clara de modelo de datos. Funciona muy bien para capas internas de dominio o estructuras intermedias.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;class&lt;/code&gt; tradicional&lt;/strong&gt;: úsala cuando el objeto necesita controlar invariantes complejas, encapsular estado mutable o exponer comportamiento más importante que los datos que almacena.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La frontera entre &lt;code&gt;dataclass&lt;/code&gt; y &lt;code&gt;class&lt;/code&gt; tradicional no es rígida. Una &lt;code&gt;dataclass&lt;/code&gt; puede tener métodos, y una clase tradicional puede almacenar datos. La clave está en comunicar intención y evitar código accidentalmente complejo.&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;No conviertas todo diccionario en &lt;code&gt;dataclass&lt;/code&gt; ni todo objeto en &lt;code&gt;TypedDict&lt;/code&gt;. Elige la estructura según el contrato que quieres expresar y el comportamiento que necesitas en el sistema.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="cierre"&gt;Cierre&lt;/h2&gt;
&lt;p&gt;Las estructuras de datos tipadas en Python nos ayudan a hacer explícitos los contratos que antes quedaban implícitos en diccionarios o clases repetitivas. &lt;code&gt;dict[str, ...]&lt;/code&gt; funciona para casos homogéneos, &lt;code&gt;TypedDict&lt;/code&gt; describe diccionarios con forma específica, &lt;code&gt;NotRequired&lt;/code&gt; y &lt;code&gt;Required&lt;/code&gt; permiten modelar campos opcionales, y &lt;code&gt;dataclass&lt;/code&gt; reduce el código necesario para representar datos con atributos.&lt;/p&gt;
&lt;p&gt;Lo importante es usar el tipado como una herramienta de diseño. Cuando la estructura comunica intención, el código se vuelve más fácil de leer, refactorizar y validar antes de llegar a producció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;&lt;p&gt;Esta es la pieza final de la serie hasta el momento. Puedes volver a la recopilación completa para repasar los conceptos anteriores sobre tipado en Python.
&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;
</content:encoded></item><item><title>Tipado en Python: Tipado de clases</title><link>https://blog.dacadev.com/python/tipado/tipado-clases/</link><pubDate>Mon, 12 Aug 2024 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/python/tipado/tipado-clases/</guid><dc:creator>Dacadev</dc:creator><category>python</category><description>Aprende tipado de clases en Python con ClassVar, Self y referencias diferidas para modelar objetos más claros y seguros.</description><media:content url="https://blog.dacadev.com/images/python/typing/classes/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="#usar-clases-como-tipos-en-python"&gt;Usar clases como tipos en Python&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#tipar-atributos-de-instancia-en-la-clase"&gt;Tipar atributos de instancia en la clase&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#classvar-para-variables-de-clase"&gt;ClassVar para variables de clase&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#referencias-hacia-la-propia-clase-con-strings"&gt;Referencias hacia la propia clase con strings&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#evaluación-diferida-con-from-__future__-import-annotations"&gt;Evaluación diferida con &lt;code&gt;from __future__ import annotations&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#typingself-para-métodos-que-devuelven-la-misma-clase"&gt;&lt;code&gt;typing.Self&lt;/code&gt; para métodos que devuelven la misma clase&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#herencia-cuando-la-clase-base-no-es-suficiente"&gt;Herencia: cuando la clase base no es suficiente&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#cierre"&gt;Cierre&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
&lt;/nav&gt;
&lt;/details&gt;

&lt;p&gt;Cuando un proyecto empieza a tener modelos de dominio, servicios y objetos que se pasan entre capas, el &lt;strong&gt;tipado de clases en Python&lt;/strong&gt; se vuelve una herramienta clave para mantener contratos claros. Ya no se trata solo de saber si una variable es &lt;code&gt;str&lt;/code&gt; o &lt;code&gt;int&lt;/code&gt;; también necesitamos expresar que un método recibe un &lt;code&gt;User&lt;/code&gt;, que un atributo guarda un &lt;code&gt;datetime&lt;/code&gt;, o que una operación entre contadores devuelve otro contador compatible.&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;Este artículo es parte de una serie que explica 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;p&gt;En esta entrega nos concentraremos en clases: cómo usarlas como tipos, cómo declarar atributos de instancia, cuándo aplicar &lt;code&gt;ClassVar&lt;/code&gt;, y cómo resolver referencias hacia la propia clase con strings, &lt;code&gt;from __future__ import annotations&lt;/code&gt; y &lt;code&gt;typing.Self&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="usar-clases-como-tipos-en-python"&gt;Usar clases como tipos en Python&lt;/h2&gt;
&lt;p&gt;En Python, una clase también puede usarse como anotación de tipo. Esto aplica tanto para clases que tú defines como para clases de la librería estándar. Por ejemplo, el módulo &lt;a href="https://docs.python.org/3/library/datetime.html"




 target="_blank"
 


&gt;&lt;code&gt;datetime&lt;/code&gt;&lt;/a&gt; define tipos como &lt;code&gt;date&lt;/code&gt;, &lt;code&gt;datetime&lt;/code&gt; y &lt;code&gt;timedelta&lt;/code&gt;, mientras que &lt;a href="https://docs.python.org/3/library/uuid.html"




 target="_blank"
 


&gt;&lt;code&gt;uuid&lt;/code&gt;&lt;/a&gt; define &lt;code&gt;UUID&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;datetime&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;uuid&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;birth_date&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;datetime&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;date&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;datetime&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;date&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;2020&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;7&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;timestamp&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;datetime&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;datetime&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;datetime&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;datetime&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;2020&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;2&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;7&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;10&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:#e06c75"&gt;duration&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;datetime&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;timedelta&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;datetime&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;timedelta&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;hours&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:#e06c75"&gt;uid1&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;uuid&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;UUID&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;uuid&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;uuid1&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;uid4&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;uuid&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;UUID&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;uuid&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;uuid4&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Este código no cambia el comportamiento en tiempo de ejecución. Su valor está en la señal que le entregamos al IDE, al analizador estático y a otros desarrolladores que lean 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:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;created_at&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;datetime&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;datetime&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;datetime&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;datetime&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;now&lt;/span&gt;() &lt;span style="color:#7f848e"&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;created_at&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;2024-08-12&amp;#34;&lt;/span&gt; &lt;span style="color:#7f848e"&gt;# ❌ el contrato dejó de ser datetime.datetime&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;Las anotaciones no reemplazan la validación de datos externos. Si recibes JSON, entrada de usuario o información desde una API, sigue siendo necesario validar en los bordes del sistema.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="tipar-atributos-de-instancia-en-la-clase"&gt;Tipar atributos de instancia en la clase&lt;/h2&gt;
&lt;p&gt;Cuando trabajamos con clases propias, podemos declarar los atributos esperados directamente en el cuerpo de la clase. Esto ayuda a que el analizador entienda qué atributos existen en cada instancia, incluso si se asignan dentro de &lt;code&gt;__init__&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;Counter&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;n&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;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;start&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:#d19a66"&gt;0&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;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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:#56b6c2;font-weight:bold"&gt;__repr__&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;str&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;n&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En este ejemplo, &lt;code&gt;n: int&lt;/code&gt; describe un &lt;strong&gt;atributo de instancia&lt;/strong&gt;. Cada objeto &lt;code&gt;Counter&lt;/code&gt; tendrá su propio valor de &lt;code&gt;n&lt;/code&gt;, asignado en el 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:#e06c75"&gt;counter&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Counter&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;start&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 style="color:#e5c07b"&gt;print&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;counter&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;n&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# ✅ 10&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:#e5c07b"&gt;repr&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;counter&lt;/span&gt;)) &lt;span style="color:#7f848e"&gt;# ✅ &amp;#34;10&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;counter&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&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:#98c379"&gt;&amp;#34;10&amp;#34;&lt;/span&gt; &lt;span style="color:#7f848e"&gt;# ❌ rompe el contrato declarado para la instancia&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La anotación en el cuerpo de la clase no inicializa el atributo por sí sola. Si declaras &lt;code&gt;n: int&lt;/code&gt;, pero nunca asignas &lt;code&gt;self.n&lt;/code&gt;, la instancia no tendrá ese atributo disponible en tiempo de ejecución.&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;Anotar un atributo no es lo mismo que crearlo. La anotación describe el contrato; la asignación en &lt;code&gt;__init__&lt;/code&gt; crea el estado real de la instancia.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="classvar-para-variables-de-clase"&gt;ClassVar para variables de clase&lt;/h2&gt;
&lt;p&gt;No todos los atributos declarados en una clase pertenecen a cada instancia. Algunas variables funcionan como configuración compartida para todas las instancias. Para estos casos existe &lt;a href="https://docs.python.org/3/library/typing.html#typing.ClassVar"




 target="_blank"
 


&gt;&lt;code&gt;ClassVar&lt;/code&gt;&lt;/a&gt;, disponible desde &lt;code&gt;typing&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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;ClassVar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;Counter&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;STEP&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;ClassVar&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:#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;n&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;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;start&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:#d19a66"&gt;0&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;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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:#56b6c2;font-weight:bold"&gt;__repr__&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;str&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;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:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;increment&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;n&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;STEP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;STEP&lt;/code&gt; representa una &lt;strong&gt;variable de clase&lt;/strong&gt;. El valor vive en la clase &lt;code&gt;Counter&lt;/code&gt;, no como parte del estado individual de cada 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-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;Counter&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;STEP&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;# ✅ configuración compartida&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;counter&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Counter&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:#e06c75"&gt;counter&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;increment&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;counter&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;n&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# 12&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;counter&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;STEP&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;5&lt;/span&gt; &lt;span style="color:#7f848e"&gt;# ❌ puede ocultar la variable de clase en esa instancia&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Técnicamente Python permite asignar &lt;code&gt;counter.STEP = 5&lt;/code&gt;, pero eso crea o modifica un atributo en la instancia, lo cual puede generar confusión. &lt;code&gt;ClassVar&lt;/code&gt; permite que herramientas como mypy o Pyright detecten este uso como una señal de diseño incorrecta.&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;Usa &lt;code&gt;ClassVar&lt;/code&gt; cuando el atributo describe configuración, constantes o metadatos compartidos por todas las instancias de una clase.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="referencias-hacia-la-propia-clase-con-strings"&gt;Referencias hacia la propia clase con strings&lt;/h2&gt;
&lt;p&gt;Un caso común aparece cuando un método recibe o devuelve otra instancia de la misma clase. Por ejemplo, podemos definir la suma de dos contadores con &lt;code&gt;__add__&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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;ClassVar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;Counter&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;STEP&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;ClassVar&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:#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;n&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;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;start&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:#d19a66"&gt;0&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;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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:#56b6c2;font-weight:bold"&gt;__repr__&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;str&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;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:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__add__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;other&lt;/span&gt;: &lt;span style="color:#98c379"&gt;&amp;#34;Counter&amp;#34;&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;Counter&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;Counter&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;start&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;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;other&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La anotación &lt;code&gt;&amp;quot;Counter&amp;quot;&lt;/code&gt; es una &lt;strong&gt;referencia adelantada&lt;/strong&gt; o &lt;em&gt;forward reference&lt;/em&gt;. Se escribe como string porque, mientras Python está evaluando el cuerpo de la clase, el nombre &lt;code&gt;Counter&lt;/code&gt; todavía no terminó de definirse.&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;first&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Counter&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;second&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Counter&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:#e06c75"&gt;result&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;first&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;second&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;result&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# 5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El siguiente diagrama resume el contrato principal de la clase:&lt;/p&gt;
&lt;pre class="mermaid"&gt;classDiagram
 class Counter {
 +int n
 +ClassVar~int~ STEP
 +__init__(int start) None
 +__repr__() str
 +__add__(Counter other) Counter
 }
&lt;/pre&gt;

&lt;p&gt;Esta forma es compatible con versiones antiguas de Python y sigue siendo frecuente en bases de código que necesitan soportar varios entornos.&lt;/p&gt;
&lt;h2 id="evaluación-diferida-con-from-__future__-import-annotations"&gt;Evaluación diferida con &lt;code&gt;from __future__ import annotations&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Desde Python 3.7 podemos activar la evaluación diferida de anotaciones usando &lt;code&gt;from __future__ import annotations&lt;/code&gt;. Con esto, las anotaciones no se resuelven inmediatamente al definir la clase, lo que permite escribir &lt;code&gt;Counter&lt;/code&gt; sin comillas.&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;__future__&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;annotations&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;ClassVar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;Counter&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;STEP&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;ClassVar&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:#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;n&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;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;start&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:#d19a66"&gt;0&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;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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:#56b6c2;font-weight:bold"&gt;__repr__&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;str&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;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:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__add__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;other&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Counter&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Counter&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;Counter&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;start&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;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;other&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La ventaja principal es legibilidad. El código se ve más cercano a una anotación normal y reduce el ruido de comillas en modelos con muchas referencias cruzadas.&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;# ✅ con evaluación diferida&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;__future__&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;annotations&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;Node&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;parent&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Node&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:#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;parent&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Node&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:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;None&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;parent&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;parent&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;&lt;code&gt;from __future__ import annotations&lt;/code&gt; debe aparecer al inicio del archivo, antes de otros imports normales. Es una decisión por módulo, no por clase.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="typingself-para-métodos-que-devuelven-la-misma-clase"&gt;&lt;code&gt;typing.Self&lt;/code&gt; para métodos que devuelven la misma clase&lt;/h2&gt;
&lt;p&gt;Python 3.11 incorporó &lt;a href="https://docs.python.org/3/library/typing.html#typing.Self"




 target="_blank"
 


&gt;&lt;code&gt;typing.Self&lt;/code&gt;&lt;/a&gt; para expresar que un método devuelve una instancia del mismo tipo concreto que lo invoca. Esto es especialmente útil en métodos fluidos, constructores alternativos y operaciones que deberían preservar el subtipo.&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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;Counter&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e06c75"&gt;n&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;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;start&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:#d19a66"&gt;0&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;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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:#56b6c2;font-weight:bold"&gt;__repr__&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;str&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;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:#c678dd"&gt;def&lt;/span&gt; &lt;span style="color:#56b6c2;font-weight:bold"&gt;__add__&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;other&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Self&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&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;type&lt;/span&gt;(&lt;span style="color:#e5c07b"&gt;self&lt;/span&gt;)(&lt;span style="color:#e06c75"&gt;start&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;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;other&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Aquí usamos &lt;code&gt;type(self)(...)&lt;/code&gt; en lugar de &lt;code&gt;Counter(...)&lt;/code&gt; para respetar el tipo concreto de la instancia. Si más adelante existe una subclase de &lt;code&gt;Counter&lt;/code&gt;, el método tiene mejores posibilidades de devolver esa misma subclase.&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;Si anotas un método con &lt;code&gt;Self&lt;/code&gt;, procura que la implementación realmente devuelva el mismo tipo concreto. Anotar &lt;code&gt;Self&lt;/code&gt; pero retornar siempre &lt;code&gt;Counter(...)&lt;/code&gt; puede engañar al analizador estático.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="herencia-cuando-la-clase-base-no-es-suficiente"&gt;Herencia: cuando la clase base no es suficiente&lt;/h2&gt;
&lt;p&gt;El beneficio de &lt;code&gt;Self&lt;/code&gt; se ve más claro con herencia. Consideremos una clase base &lt;code&gt;A&lt;/code&gt; y una subclase &lt;code&gt;B&lt;/code&gt;. Si el método &lt;code&gt;me&lt;/code&gt; se anota devolviendo &lt;code&gt;A&lt;/code&gt;, el tipo estático del resultado será siempre &lt;code&gt;A&lt;/code&gt;, incluso cuando el objeto real sea &lt;code&gt;B&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;__future__&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;annotations&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;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;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;me&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;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;return&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&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;B&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;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:#e06c75"&gt;b&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;B&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;result&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:#e06c75"&gt;me&lt;/span&gt;() &lt;span style="color:#7f848e"&gt;# tipo estático: A&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ese contrato es correcto, pero pierde información. El método devuelve &lt;code&gt;self&lt;/code&gt;, así que cuando lo invoca una instancia de &lt;code&gt;B&lt;/code&gt;, el resultado debería conservar el tipo &lt;code&gt;B&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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;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;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;me&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;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&gt;&lt;/span&gt;&lt;span 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;B&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;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:#e06c75"&gt;b&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;B&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;result&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:#e06c75"&gt;me&lt;/span&gt;() &lt;span style="color:#7f848e"&gt;# tipo estático: B&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La diferencia es importante cuando encadenas métodos o cuando la subclase agrega comportamiento adicional.&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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;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;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;me&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;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&gt;&lt;/span&gt;&lt;span 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;B&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;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;only_b&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;B&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;b&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;B&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;b&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;me&lt;/span&gt;()&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;only_b&lt;/span&gt;()) &lt;span style="color:#7f848e"&gt;# ✅ el analizador conserva que b.me() es B&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Sin &lt;code&gt;Self&lt;/code&gt;, el analizador puede asumir que &lt;code&gt;b.me()&lt;/code&gt; es &lt;code&gt;A&lt;/code&gt;, y por tanto marcar &lt;code&gt;only_b()&lt;/code&gt; como un método inexistente.&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;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;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;me&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;A&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;self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;B&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;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;only_b&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;B&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;b&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;B&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:#e06c75"&gt;me&lt;/span&gt;()&lt;span style="color:#56b6c2"&gt;.&lt;/span&gt;&lt;span style="color:#e06c75"&gt;only_b&lt;/span&gt;() &lt;span style="color:#7f848e"&gt;# ❌ para el analizador, me() devuelve A&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;Usa &lt;code&gt;Self&lt;/code&gt; cuando el contrato del método sea “devuelvo el mismo tipo concreto que recibió la llamada”. Usa el nombre de la clase cuando el método debe devolver explícitamente una instancia de esa clase base.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="cierre"&gt;Cierre&lt;/h2&gt;
&lt;p&gt;El tipado de clases permite expresar contratos más precisos entre objetos. Puedes usar clases estándar como &lt;code&gt;datetime.datetime&lt;/code&gt; o &lt;code&gt;uuid.UUID&lt;/code&gt;, declarar atributos de instancia, diferenciar variables compartidas con &lt;code&gt;ClassVar&lt;/code&gt;, y manejar referencias hacia la propia clase con strings o evaluación diferida.&lt;/p&gt;
&lt;p&gt;Para jerarquías de herencia, &lt;code&gt;typing.Self&lt;/code&gt; mejora la precisión del análisis estático porque conserva el tipo concreto de la instancia. Esta diferencia se vuelve relevante cuando diseñas APIs orientadas a objetos, métodos encadenables o modelos que se especializan mediante subclases.&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;En el próximo artículo veremos cómo aplicar tipado a estructuras de datos para modelar colecciones más expresivas y mantenibles.
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.dacadev.com/python/tipado/estructuras-de-datos" class="btn btn-outline-primary " rel="" &gt;Estructuras de datos&lt;/a&gt;&lt;/p&gt;
&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>Tipado en Python: Tipado de funciones</title><link>https://blog.dacadev.com/python/tipado/tipado-funciones/</link><pubDate>Sun, 11 Aug 2024 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/python/tipado/tipado-funciones/</guid><dc:creator>Dacadev</dc:creator><category>python</category><description>Aprende tipado de funciones en Python con type hints, valores por defecto, *args y Callable mediante ejemplos prácticos.</description><media:content url="https://blog.dacadev.com/images/python/typing/functions/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="#sintaxis-general-para-tipar-funciones"&gt;Sintaxis general para tipar funciones&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#ejemplo-con-counter"&gt;Ejemplo con &lt;code&gt;Counter&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#valores-por-defecto-tipados"&gt;Valores por defecto tipados&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#args-tipados"&gt;&lt;code&gt;*args&lt;/code&gt; tipados&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#args-con-parámetros-keyword-only"&gt;&lt;code&gt;*args&lt;/code&gt; con parámetros keyword-only&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#funciones-de-primer-orden-y-callable"&gt;Funciones de primer orden y &lt;code&gt;Callable&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#callable-con-clases-y-__call__"&gt;&lt;code&gt;Callable&lt;/code&gt; con clases y &lt;code&gt;__call__&lt;/code&gt;&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 un módulo crece y varias funciones empiezan a pasar datos entre capas, el contrato entre parámetros y retorno se vuelve crítico. El &lt;strong&gt;tipado de funciones en Python&lt;/strong&gt; nos permite documentar ese contrato directamente en el código, mejorar la autocompletación del IDE y detectar inconsistencias antes de ejecutar el flujo completo en producció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;&lt;p&gt;Este artículo es parte de una serie que explica 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;p&gt;En la entrega anterior vimos cómo anotar variables y colecciones. Ahora aplicaremos esa misma idea en funciones: parámetros, retornos, valores por defecto, argumentos dinámicos y objetos que se pueden invocar como funciones.&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;Las anotaciones de tipo no cambian el comportamiento de Python en tiempo de ejecución. Su valor principal está en herramientas de análisis estático como &lt;code&gt;mypy&lt;/code&gt;, &lt;code&gt;pyright&lt;/code&gt;, IDEs y revisiones de código.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="sintaxis-general-para-tipar-funciones"&gt;Sintaxis general para tipar funciones&lt;/h2&gt;
&lt;p&gt;La sintaxis base para agregar tipos a una función consiste en anotar cada argumento después de &lt;code&gt;:&lt;/code&gt; y declarar el tipo de retorno después de &lt;code&gt;-&amp;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-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;my_function&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;arg1&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;type&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;arg2&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;type&lt;/span&gt;) &lt;span style="color:#56b6c2"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color:#e06c75"&gt;return_type&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Esta estructura expresa dos cosas importantes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;arg1: type&lt;/code&gt;: el argumento &lt;code&gt;arg1&lt;/code&gt; debería recibir valores compatibles con &lt;code&gt;type&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-&amp;gt; return_type&lt;/code&gt;: la función debería devolver un valor compatible con &lt;code&gt;return_type&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Por ejemplo, una función que recibe dos enteros y retorna otro entero se puede escribir así:&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;add&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;a&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;b&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;a&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;+&lt;/span&gt; &lt;span style="color:#e06c75"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Si la función no retorna un valor útil, se usa &lt;code&gt;None&lt;/code&gt; como tipo de retorno:&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;log_message&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:#e06c75"&gt;message&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;Anotar el retorno es tan importante como anotar los argumentos. Muchas inconsistencias aparecen cuando una función empieza devolviendo &lt;code&gt;int&lt;/code&gt;, luego en una rama retorna &lt;code&gt;None&lt;/code&gt; y el consumidor asume que siempre puede operar con números.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="ejemplo-con-counter"&gt;Ejemplo con &lt;code&gt;Counter&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Supongamos que tenemos una lista de elementos y cada elemento contiene una lista de etiquetas. Queremos contar cuántas veces aparece cada etiqueta.&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;Counter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;counter_tags&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;items&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;dict&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;list&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;Counter&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:#e06c75"&gt;Counter&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;tag&lt;/span&gt; &lt;span style="color:#c678dd"&gt;for&lt;/span&gt; &lt;span style="color:#e06c75"&gt;item&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:#c678dd"&gt;for&lt;/span&gt; &lt;span style="color:#e06c75"&gt;tag&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;in&lt;/span&gt; &lt;span style="color:#e06c75"&gt;item&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La firma de &lt;code&gt;counter_tags&lt;/code&gt; nos dice que &lt;code&gt;items&lt;/code&gt; debe ser una lista de diccionarios. Cada diccionario usa llaves de tipo &lt;code&gt;str&lt;/code&gt; y valores de tipo &lt;code&gt;list[str]&lt;/code&gt;. La función retorna un &lt;code&gt;Counter[str]&lt;/code&gt;, es decir, un contador cuyas llaves son cadenas.&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;counter_tags&lt;/span&gt;([{&lt;span style="color:#98c379"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;: [&lt;span style="color:#98c379"&gt;&amp;#34;python&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;typing&amp;#34;&lt;/span&gt;]}, {&lt;span style="color:#98c379"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;: [&lt;span style="color:#98c379"&gt;&amp;#34;python&amp;#34;&lt;/span&gt;]}]) &lt;span style="color:#7f848e"&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;counter_tags&lt;/span&gt;([{&lt;span style="color:#98c379"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;: [&lt;span style="color:#98c379"&gt;&amp;#34;python&amp;#34;&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;1&lt;/span&gt;]}, {&lt;span style="color:#98c379"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;: [&lt;span style="color:#98c379"&gt;&amp;#34;typing&amp;#34;&lt;/span&gt;]}]) &lt;span style="color:#7f848e"&gt;# ❌&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La segunda llamada es problemática porque la lista de &lt;code&gt;tags&lt;/code&gt; mezcla &lt;code&gt;str&lt;/code&gt; con &lt;code&gt;int&lt;/code&gt;. Python puede ejecutarla, pero un analizador estático marcará que &lt;code&gt;1&lt;/code&gt; no coincide con &lt;code&gt;list[str]&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;El tipado describe la forma esperada de los datos, pero no reemplaza validaciones de entrada cuando los datos vienen de usuarios, APIs externas, archivos o mensajes de una cola.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="valores-por-defecto-tipados"&gt;Valores por defecto tipados&lt;/h2&gt;
&lt;p&gt;Cuando una función tiene valores por defecto, también conviene anotar esos parámetros. El valor asignado debe ser compatible con el tipo declarado.&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;sum_numbers&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;numbers&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:#e06c75"&gt;start&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:#d19a66"&gt;0&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:#e06c75"&gt;total&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;in&lt;/span&gt; &lt;span style="color:#e06c75"&gt;numbers&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&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:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;total&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;sum_numbers&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:#d19a66"&gt;4&lt;/span&gt;], &lt;span style="color:#e06c75"&gt;start&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;# ✅&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;sum_numbers&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:#d19a66"&gt;4&lt;/span&gt;]) &lt;span style="color:#7f848e"&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;sum_numbers&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:#98c379"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;]) &lt;span style="color:#7f848e"&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;sum_numbers&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:#d19a66"&gt;4&lt;/span&gt;], &lt;span style="color:#e06c75"&gt;start&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;B&amp;#34;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# ❌&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En este caso &lt;code&gt;numbers&lt;/code&gt; debe ser una lista de enteros y &lt;code&gt;start&lt;/code&gt; también debe ser un entero. Si no se pasa &lt;code&gt;start&lt;/code&gt;, Python usa &lt;code&gt;0&lt;/code&gt;, que cumple con la anotación &lt;code&gt;int&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Este patrón es útil en funciones acumuladoras, paginadores, transformaciones de datos y cualquier API interna donde un valor opcional modifica el cálculo sin cambiar el tipo esperado.&lt;/p&gt;
&lt;h2 id="args-tipados"&gt;&lt;code&gt;*args&lt;/code&gt; tipados&lt;/h2&gt;
&lt;p&gt;Python permite recibir una cantidad variable de argumentos posicionales con &lt;code&gt;*args&lt;/code&gt;. Para tiparlos, se anota el tipo de cada elemento recibido, no el tipo de la tupla completa.&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;sum_args&lt;/span&gt;(&lt;span style="color:#56b6c2"&gt;*&lt;/span&gt;&lt;span style="color:#e06c75"&gt;args&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:#e06c75"&gt;total&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;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;in&lt;/span&gt; &lt;span style="color:#e06c75"&gt;args&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&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:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;total&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;sum_args&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:#d19a66"&gt;4&lt;/span&gt;, &lt;span style="color:#d19a66"&gt;5&lt;/span&gt;) &lt;span style="color:#7f848e"&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;sum_args&lt;/span&gt;(&lt;span style="color:#d19a66"&gt;1&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# ❌&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La anotación &lt;code&gt;*args: int&lt;/code&gt; significa que cada argumento posicional adicional debe ser &lt;code&gt;int&lt;/code&gt;. Internamente, Python sigue recibiendo una tupla, pero desde el punto de vista del contrato de la función, cada elemento debe respetar el tipo indicado.&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 necesitas aceptar varios tipos en &lt;code&gt;*args&lt;/code&gt;, puedes combinar tipos con &lt;code&gt;|&lt;/code&gt;, por ejemplo &lt;code&gt;*args: int | float&lt;/code&gt;. Esto mantiene el contrato explícito sin convertir la función en una entrada completamente abierta.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="args-con-parámetros-keyword-only"&gt;&lt;code&gt;*args&lt;/code&gt; con parámetros keyword-only&lt;/h2&gt;
&lt;p&gt;También podemos combinar argumentos dinámicos con parámetros que solo se reciben por nombre. En Python, todo parámetro declarado después de &lt;code&gt;*args&lt;/code&gt; se vuelve &lt;strong&gt;keyword-only&lt;/strong&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;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;sum_args&lt;/span&gt;(&lt;span style="color:#56b6c2"&gt;*&lt;/span&gt;&lt;span style="color:#e06c75"&gt;args&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;start&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:#d19a66"&gt;0&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:#e06c75"&gt;total&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;n&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;in&lt;/span&gt; &lt;span style="color:#e06c75"&gt;args&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&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:#c678dd"&gt;return&lt;/span&gt; &lt;span style="color:#e06c75"&gt;total&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;sum_args&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:#d19a66"&gt;4&lt;/span&gt;) &lt;span style="color:#7f848e"&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;sum_args&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:#e06c75"&gt;start&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;# ✅&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;sum_args&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:#e06c75"&gt;start&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;=&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;x&amp;#34;&lt;/span&gt;) &lt;span style="color:#7f848e"&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;sum_args&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:#98c379"&gt;&amp;#34;3&amp;#34;&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# ❌&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Aquí &lt;code&gt;start&lt;/code&gt; no puede pasarse como otro argumento posicional más; debe enviarse usando su nombre. Esto mejora la legibilidad cuando el parámetro tiene un rol especial dentro del cálculo.&lt;/p&gt;
&lt;p&gt;Este estilo es recomendable cuando una función acepta una secuencia flexible de valores, pero también necesita opciones de configuración con nombres claros.&lt;/p&gt;
&lt;h2 id="funciones-de-primer-orden-y-callable"&gt;Funciones de primer orden y &lt;code&gt;Callable&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;En Python podemos pasar funciones como argumentos de otras funciones. Para anotar este tipo de contrato usamos &lt;code&gt;Callable&lt;/code&gt;, disponible en &lt;a href="https://docs.python.org/3/library/collections.abc.html#collections.abc.Callable"




 target="_blank"
 


&gt;&lt;code&gt;collections.abc&lt;/code&gt;&lt;/a&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;time&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;collections.abc&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Callable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;work&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;send_notification&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Callable&lt;/span&gt;[[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;], &lt;span style="color:#e5c07b"&gt;None&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;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:#d19a66"&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;time&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&gt;&lt;/span&gt;&lt;span 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;send_notification&lt;/span&gt;(&lt;span style="color:#98c379"&gt;f&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#34;Finished &lt;/span&gt;&lt;span style="color:#98c379"&gt;{&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:#98c379"&gt;}&lt;/span&gt;&lt;span style="color:#98c379"&gt; rounds of work!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La anotación &lt;code&gt;Callable[[str], None]&lt;/code&gt; indica que &lt;code&gt;send_notification&lt;/code&gt; debe ser invocable, recibir un &lt;code&gt;str&lt;/code&gt; y no retornar un valor útil.&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;notify&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:#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;def&lt;/span&gt; &lt;span style="color:#61afef;font-weight:bold"&gt;bad_notify&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;message&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;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:#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;work&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;notify&lt;/span&gt;) &lt;span style="color:#7f848e"&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;work&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;bad_notify&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# ❌&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;Callable&lt;/code&gt;, el primer bloque define la lista de argumentos y el segundo define el retorno:&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;Callable&lt;/span&gt;[[&lt;span style="color:#e5c07b"&gt;str&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;Callable&lt;/span&gt;[[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;int&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:#e06c75"&gt;Callable&lt;/span&gt;[[&lt;span style="color:#e5c07b"&gt;bytes&lt;/span&gt;], &lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre class="mermaid"&gt;flowchart LR
 A[&amp;#34;Callable[[str, int], bool]&amp;#34;] --&amp;gt; B[Entrada 1: str]
 A --&amp;gt; C[Entrada 2: int]
 B --&amp;gt; D[Función compatible]
 C --&amp;gt; D
 D --&amp;gt; E[Salida: bool]
&lt;/pre&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;Usa &lt;code&gt;Callable&lt;/code&gt; cuando la función consumidora solo necesita ejecutar un comportamiento. Esto reduce acoplamiento porque no obliga a depender de una implementación concreta.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="callable-con-clases-y-__call__"&gt;&lt;code&gt;Callable&lt;/code&gt; con clases y &lt;code&gt;__call__&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Callable&lt;/code&gt; no se limita a funciones definidas con &lt;code&gt;def&lt;/code&gt;. Una instancia de clase también puede ser invocable si implementa el método especial &lt;code&gt;__call__&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;Notifier&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;__call__&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;Notifier sends: &amp;#39;&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;#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:#e06c75"&gt;notifier&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Notifier&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;work&lt;/span&gt;(&lt;span style="color:#e06c75"&gt;notifier&lt;/span&gt;) &lt;span style="color:#7f848e"&gt;# ✅&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En este ejemplo, &lt;code&gt;notifier&lt;/code&gt; se comporta como una función porque &lt;code&gt;Notifier&lt;/code&gt; define &lt;code&gt;__call__&lt;/code&gt;. Para el contrato de &lt;code&gt;work&lt;/code&gt;, lo importante es que el objeto pueda invocarse con un &lt;code&gt;str&lt;/code&gt; y retornar &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Este patrón aparece con frecuencia cuando necesitas combinar estado interno con una interfaz funcional. Por ejemplo, un notificador podría guardar credenciales, configuración del canal o métricas, pero seguir exponiendo una firma simple para el consumidor.&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;No confundas &lt;code&gt;Callable&lt;/code&gt; con una clase específica. &lt;code&gt;Callable[[str], None]&lt;/code&gt; describe una capacidad de invocación; no exige que el objeto sea una función tradicional ni una instancia de una clase concreta.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="conclusión"&gt;Conclusión&lt;/h2&gt;
&lt;p&gt;El tipado de funciones en Python permite hacer explícitos los contratos entre piezas de código: qué argumentos acepta una función, qué retorna y qué forma deben tener los callables que recibe como dependencias.&lt;/p&gt;
&lt;p&gt;En código de aplicación, estas anotaciones mejoran la navegación, reducen errores de integración y facilitan refactors. En librerías o módulos compartidos, además funcionan como documentación ejecutable para otros desarrolladores y herramientas.&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;En el siguiente artículo continuaremos con el tipado aplicado a clases, atributos y métodos.
&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.dacadev.com/python/tipado/tipado-clases" class="btn btn-outline-primary " rel="" &gt;Tipado en clases&lt;/a&gt;&lt;/p&gt;
&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
</content:encoded></item><item><title>Tipado básico en Python</title><link>https://blog.dacadev.com/python/tipado/tipado-basico/</link><pubDate>Sat, 10 Aug 2024 00:00:00 -0500</pubDate><guid>https://blog.dacadev.com/python/tipado/tipado-basico/</guid><dc:creator>Dacadev</dc:creator><category>python</category><description>Aprende a aplicar tipos en Python de manera efectiva. Descubre cómo agregar tipado en variables, colecciones, y funciones en Python. Incluye ejemplos prácticos y recomendaciones según la versión de Python.</description><media:content url="https://blog.dacadev.com/images/python/typing/bases/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="#tipos-buitl-in-in-python"&gt;Tipos Buitl-in in Python&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#tipado-en-colecciones"&gt;Tipado en colecciones&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#combinación-de-tipos-en-python"&gt;Combinación de Tipos en Python&lt;/a&gt;
 &lt;ol&gt;
 &lt;li&gt;&lt;a href="#definir-más-de-un-tipo"&gt;Definir Más de un Tipo&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#valores-opcionales-o-none"&gt;Valores Opcionales o &lt;code&gt;None&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#definir-valores-fijos"&gt;Definir Valores Fijos&lt;/a&gt;&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/li&gt;
 &lt;li&gt;&lt;a href="#definir-tipos-personalizados"&gt;Definir Tipos Personalizados&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="#datos-io-en-python"&gt;Datos IO en Python&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;&lt;p&gt;Este artículo es parte de una serie que explica 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;p&gt;Agregar tipos en Python es muy sencillo y tiene una sintaxis similar a otros lenguajes como &lt;em&gt;Typescript&lt;/em&gt;. &lt;strong&gt;No es obligatorio&lt;/strong&gt; aplicar tipado en cada pieza de código, lo que permite agregarlo de manera gradual. Además, agregar o no tipos no afectará el comportamiento del código.&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;La posibilidad de agregar tipado en Python está disponible desde la versión &lt;strong&gt;3.5&lt;/strong&gt;. Desde entonces, se han añadido nuevas características y mejoras.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="tipos-buitl-in-in-python"&gt;Tipos Buitl-in in Python&lt;/h2&gt;
&lt;p&gt;Los tipos &lt;em&gt;built-in&lt;/em&gt; son aquellos que vienen por defecto en Python, como &lt;code&gt;str&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt;, &lt;code&gt;bool&lt;/code&gt;, &lt;code&gt;bytes&lt;/code&gt;, &lt;code&gt;None&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;dict&lt;/code&gt;, &lt;code&gt;tuple&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt;, entre otros.&lt;/p&gt;
&lt;p&gt;Para agregar tipado a una variable, simplemente añade &lt;code&gt;:&lt;/code&gt; después del nombre de la variable y luego especifica el tipo de dato. La sintaxis es:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;variable&amp;gt;: &amp;lt;type&amp;gt; = &amp;lt;value&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;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-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;n&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:#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;f&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;float&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#d19a66"&gt;10.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;c&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;complex&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:#d19a66"&gt;2&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 style="color:#e06c75"&gt;b&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;True&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:#e5c07b"&gt;bytes&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;b&lt;/span&gt;&lt;span style="color:#98c379"&gt;&amp;#39;bytes&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;t&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;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;v&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;None&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;En el anterior ejemplo estamos definiendo que cada una de las variables solo van a manejar un tipo de datos a lo largo de vida en el programa.&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;Recuerda que el agregar el tipo de dato no afecta el comportamiento del código, es solo una ayuda para el programador, analizadores de código estáticos e IDEs.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id="tipado-en-colecciones"&gt;Tipado en colecciones&lt;/h2&gt;
&lt;p&gt;Para colecciones como &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;dict&lt;/code&gt;, &lt;code&gt;tuple&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt;, la sintaxis es similar a la de las variables simples. salvo que podemos definir o nor el tipo de variable que cada variable va a contener. es decir que tenemos dos tipos de sintaxis que podemos utilizar.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;variable&amp;gt;: &amp;lt;collection&amp;gt; = &amp;lt;value&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;variable&amp;gt;: &amp;lt;collection&amp;gt;[&amp;lt;type&amp;gt;...] = &amp;lt;value&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En la primera opción estamos definiendo que la variable va a ser de tipo &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;dict&lt;/code&gt;, &lt;code&gt;tuple&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt; y en la segunda opción estamos definiendo que la variable va a ser de tipo &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;dict&lt;/code&gt;, &lt;code&gt;tuple&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt; y que va a contener un tipo de dato especifico. Veamos como se aplica esto en algunos ejemplos, para ello es importante tener en cuenta la versión de Python que estás utilizando.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Python 3.5 a 3.8:&lt;/strong&gt; Es necesario importar los tipos de la librería &lt;code&gt;typing&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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;List&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Set&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Tuple&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Dict&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;l&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;List&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:#d19a66"&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;s&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Set&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;hello&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;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;t&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Tuple&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;str&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:#d19a66"&gt;10&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;Python&amp;#34;&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:#e06c75"&gt;d&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Dict&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&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:#98c379"&gt;&amp;#34;active&amp;#34;&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;True&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;admin&amp;#34;&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;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Python 3.9 y posteriores:&lt;/strong&gt; Puedes utilizar la sintaxis estándar sin importar &lt;code&gt;typing&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:#e06c75"&gt;l&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;list&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:#d19a66"&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;s&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;set&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;hello&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;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;t&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;tuple&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;str&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:#d19a66"&gt;10&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;Python&amp;#34;&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:#e06c75"&gt;d&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;dict&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&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:#98c379"&gt;&amp;#34;active&amp;#34;&lt;/span&gt;: &lt;span style="color:#e5c07b"&gt;True&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;admin&amp;#34;&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;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En los ejemplos anteriores podemos observar que estamos definiendo un tipo de colección diferente por cada varibale y cabe destacar que en el caso de las colecciones podemos definir el tipo de dato que va a contener cada una de las variables, debes tener en cuenta que:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;para &lt;code&gt;list&lt;/code&gt; y &lt;code&gt;set&lt;/code&gt; se utiliza el tipo de dato que va a contener entre corchetes &lt;code&gt;[]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;para &lt;code&gt;tuple&lt;/code&gt; se define el tipo de dato y la posición dentro de la tupla entre corchetes &lt;code&gt;[]&lt;/code&gt;, es decir que en el ejemplo se espera que sea una tupla de tres elementos que estaran en el siguiente orden &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;str&lt;/code&gt;, &lt;code&gt;bool&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;para &lt;code&gt;dict&lt;/code&gt; se define el tipo de dato que va a contener la llave y el valor entre corchetes &lt;code&gt;[]&lt;/code&gt;, es decir que en el ejemplo se espera que sea un diccionario con llaves de tipo &lt;code&gt;str&lt;/code&gt; y valores de tipo &lt;code&gt;bool&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="combinación-de-tipos-en-python"&gt;Combinación de Tipos en Python&lt;/h2&gt;
&lt;p&gt;En algunos casos, es necesario que las variables puedan contener más de un tipo de dato o incluso que puedan ser opcionales. Para ello se han definido diversas estrategias para alcanzar esta funcionalidad&lt;/p&gt;
&lt;h3 id="definir-más-de-un-tipo"&gt;Definir Más de un Tipo&lt;/h3&gt;
&lt;p&gt;Utiliza el carácter &lt;code&gt;|&lt;/code&gt; para definir más de un tipo de dato en una variable, este carácter actúa como un &lt;code&gt;OR&lt;/code&gt; lógico:&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;a&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;str&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;b&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;str&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;one&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Para versiones anteriores a Python 3.9, importa &lt;code&gt;Union&lt;/code&gt; de &lt;code&gt;typing&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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Union&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;a&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Union&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&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:#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;b&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Union&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&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;one&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="valores-opcionales-o-none"&gt;Valores Opcionales o &lt;code&gt;None&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Para definir que un valor es opcional, añade &lt;code&gt;None&lt;/code&gt; como parte de los tipos posibles:&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;a&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;None&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;b&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;None&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Para versiones anteriores a Python 3.9, utiliza &lt;code&gt;Optional&lt;/code&gt; o &lt;code&gt;Union&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:#7f848e"&gt;# Opción 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;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;Optional&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;a&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Optional&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:#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;# Opción 2&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;Union&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;a&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Union&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;None&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="definir-valores-fijos"&gt;Definir Valores Fijos&lt;/h3&gt;
&lt;p&gt;Si deseas restringir los valores que puede tomar una variable, usa &lt;code&gt;Literal&lt;/code&gt; de &lt;code&gt;typing&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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Literal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;cards&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;Literal&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;clubs&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;diamonds&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;hearts&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;spades&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;cards&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#98c379"&gt;&amp;#34;clubs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="definir-tipos-personalizados"&gt;Definir Tipos Personalizados&lt;/h2&gt;
&lt;p&gt;EN Python asi como con las variables es posible definir tipos personalizados, para simplificar la lectura del código o incluso para darle un mejor entendimiento al código. en la siguiente pieza de código podemos ver esta funcionalidad.&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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Literal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;UserType&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Literal&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;user&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;ID&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&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;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;PersonalData&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:#e5c07b"&gt;str&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:#e5c07b"&gt;bool&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float&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:#e06c75"&gt;User&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;tuple&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;ID&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;PersonalData&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;UserType&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;UserUgly&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;tuple&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;str&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;dict&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&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:#e5c07b"&gt;bool&lt;/span&gt;&lt;span style="color:#56b6c2"&gt;|&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;float&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;Literal&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;]]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Como podemos observa en el ejemplo anterior estamos separando nuestra definición de tipos en otros tipos para facilitar la lectura de nuestro código, en el caso de &lt;code&gt;User&lt;/code&gt; y &lt;code&gt;UserUgly&lt;/code&gt; estamos definiendo un tipo de dato que va a ser una tupla que va a contener un &lt;code&gt;ID&lt;/code&gt;, &lt;code&gt;PersonalData&lt;/code&gt; y &lt;code&gt;UserType&lt;/code&gt; y en el caso de &lt;code&gt;UserUgly&lt;/code&gt; estamos definiendo el mismo tipo de dato pero de una manera menos legible.&lt;/p&gt;
&lt;p&gt;si escribieramos el mismo código para versiones anteriores a Python 3.9, el código 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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Literal&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Union&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Optional&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;UserType&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Literal&lt;/span&gt;[&lt;span style="color:#98c379"&gt;&amp;#34;admin&amp;#34;&lt;/span&gt;, &lt;span style="color:#98c379"&gt;&amp;#34;user&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;ID&lt;/span&gt; &lt;span style="color:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e06c75"&gt;Union&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;int&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:#e06c75"&gt;PersonalData&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:#e5c07b"&gt;str&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;Optional&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;, &lt;span style="color:#e5c07b"&gt;bool&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&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:#56b6c2"&gt;=&lt;/span&gt; &lt;span style="color:#e5c07b"&gt;tuple&lt;/span&gt;[&lt;span style="color:#e06c75"&gt;ID&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;PersonalData&lt;/span&gt;, &lt;span style="color:#e06c75"&gt;UserType&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="datos-io-en-python"&gt;Datos IO en Python&lt;/h2&gt;
&lt;p&gt;Cuando trabajes con datos de entrada/salida, como la lectura de archivos, usa el tipo &lt;code&gt;IO&lt;/code&gt; de &lt;code&gt;typing&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;typing&lt;/span&gt; &lt;span style="color:#c678dd"&gt;import&lt;/span&gt; &lt;span style="color:#e06c75"&gt;IO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span 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;text_file&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;IO&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;str&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;# text, json, xml, html...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e06c75"&gt;bin_file&lt;/span&gt;: &lt;span style="color:#e06c75"&gt;IO&lt;/span&gt;[&lt;span style="color:#e5c07b"&gt;bytes&lt;/span&gt;] &lt;span style="color:#7f848e"&gt;# jpeg, png, pdf, mp3...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;El tipo &lt;code&gt;IO&lt;/code&gt; es un tipo genérico que se utiliza para representar objetos que son streams de entrada o salida, como archivos y sockets, y solo admite tipos de datos &lt;code&gt;str&lt;/code&gt; y &lt;code&gt;bytes&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;&lt;p&gt;En este artículo, hemos cubierto las nociones básicas sobre cómo agregar tipos a tus variables en Python. En el próximo artículo, exploraremos cómo agregar tipos a funciones.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.dacadev.com/python/tipado/tipado-funciones" class="btn btn-outline-primary " rel="" &gt;Tipado de funciones&lt;/a&gt;&lt;/p&gt;
&lt;/p&gt;&lt;/div&gt;
&lt;/div&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></channel></rss>