<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Felipe Navarro - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Descubre miles de cursos de programación escritos por expertos. Aprende Desarrollo Web, Ciencia de Datos, DevOps, Seguridad y obtén asesoramiento profesional para desarrolladores. ]]>
        </description>
        <link>https://www.freecodecamp.org/espanol/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Felipe Navarro - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/espanol/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 14 May 2026 19:58:34 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/espanol/news/author/felipe-navarro/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ find() vs filter() en JavaScript – Las diferencias explicadas a través de ejemplos ]]>
                </title>
                <description>
                    <![CDATA[ Una pregunta que se suele dar con mucha frecuencia en las entrevistas a desarrolladores de JavaScript es explicar la diferencia entre los métodos find() y filter(). En este tutorial, veremos qué son estos métodos y cuándo debes usarlos. ¿Qué es el método filter()? Este método devuelve todos los elementos de ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/find-vs-filter-en-javascript-las-diferencias-a-traves-de-ejemplos/</link>
                <guid isPermaLink="false">65907178e058cc03f9581187</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Felipe Navarro ]]>
                </dc:creator>
                <pubDate>Fri, 19 Jan 2024 06:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2023/12/Logo.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/find-vs-filter-javascript/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">find() vs filter() in JavaScript – Differences Explained with Examples</a>
      </p><p>Una pregunta que se suele dar con mucha frecuencia en las entrevistas a desarrolladores de JavaScript es explicar la diferencia entre los métodos find() y filter().</p><p>En este tutorial, veremos qué son estos métodos y cuándo debes usarlos.</p><h2 id="-qu-es-el-m-todo-filter-">¿Qué es el método <code>filter()</code>?</h2><p>Este método devuelve todos los elementos de un arreglo que satisfacen la condición especificada en la función del callback (retrollamada).</p><p>Veamos con un ejemplo cómo funciona:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">const x = [1, 2, 3, 4, 5];

const y = x.filter(el =&gt; el*2 === 2);

console.log("y es: ", y); // y es: [1]</code></pre><figcaption>Ejemplo de filter()</figcaption></figure><p>Examinando la salida del ejemplo anterior, vemos que el <strong>valor de y es un arreglo con 1 elemento</strong>, el único del arreglo x que cumple la condición: se ha <em>filtrado</em> el arreglo. El método filter() itera sobre todos los elementos de un arreglo y devuelve otro arreglo con los elementos que cumplen la condición especificada en la función de callback.</p><h2 id="-qu-es-el-m-todo-find-">¿Qué es el método <code>find()</code>?</h2><p>Este método devuelve el primer elemento de un arreglo que satisface la condición especificada en la función de callback.</p><p>Como en el punto anterior, veamos un ejemplo:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">const x = [1, 2, 3, 4, 5];

const y = x.find(el =&gt; el*2 === 2);

console.log("y es: ", y); // y es: 1</code></pre><figcaption>Ejemplo de find()</figcaption></figure><p>Vemos que el <strong>valor de y es 1</strong>. El lector poco atento dirá: "lo mismo que antes, con filter()". ¡No! Con filter() se obtenía un arreglo con un elemento, se recorre el arreglo entero en busca de todos los elementos que cumplan la condición; find() comienza a iterar pero se detiene en cuanto encuentra un valor que cumpla la condición y lo devuelve. Por eso no devuelve un arreglo, solo va a devolver ese primer valor que encuentre, haya lo que haya después.</p><p>Resumiendo:</p><ol><li><code>filter()</code> devuelve un arreglo con todos los elementos que cumplen la condición; <code>find()</code> devuelve el primer elemento que satisface la condición.</li><li>Con <code>filter()</code> se itera todo el arreglo; <code>find()</code> se detiene al encontrar el primer elemento que cumpla la condición.</li></ol><blockquote>Si ningún elemento cumple la condición, <code>filter()</code> devuelve un arreglo vacío, <code>[]</code>, mientras que <code>find()</code> devuelve <code>undefined</code>.</blockquote><h2 id="casos-de-uso-para-find-y-filter-">Casos de uso para <code>find()</code> y <code>filter()</code></h2><p>Cuando se quiere aplicar la condición a todo el arreglo, esperando de manera implícita que sea devuelto más de un elemento, habrá que utilizar <strong>filter()</strong>;<strong> </strong>si se espera que sólo sea devuelto un valor, se usará <strong>find()</strong> y se ahorrará el procesamiento de todo el arreglo.</p><p>Veamos un ejemplo de cada caso de uso:</p><h3 id="1-ejemplo-de-caso-de-uso-para-filter-">1. Ejemplo de caso de uso para filter()</h3><figure class="kg-card kg-code-card"><pre><code class="language-javascript">const x = [1, 2, 3, 4, 5];

const y = x.filter(el =&gt; el%2 === 0);

console.log("y es: ", y); // y es: [2, 4]</code></pre><figcaption>Ejemplo de caso de uso para filter()</figcaption></figure><p>El objetivo aquí es encontrar todos los elementos pares. Obviamente hay que utilizar <code><strong>filter()</strong></code> ya que es necesario recorrer todo el arreglo, y es muy probable que sea devuelto más de un elemento.</p><h3 id="2-ejemplo-de-caso-de-uso-para-find-">2. Ejemplo de caso de uso para find()</h3><figure class="kg-card kg-code-card"><pre><code class="language-javascript">const emp = [
    {
        nombre: "Ram",
        empID: 101
    },
    {
        nombre: "Sham",
        empID: 102
    },
    {
        nombre: "Mohan",
        empID: 103
    }
];

const res = emp.find(el =&gt; el.empID === 102);

console.log("res es: ", res); // res es: {nombre: 'Sham', empID: 102}</code></pre><figcaption>Ejemplo de caso de uso para find()</figcaption></figure><p>Aquí sin embargo tiene más sentido usar <code><strong>find()</strong></code>. Se sabe que los posibles valores que puede tomar <code>empID</code> son únicos, por lo que una búsqueda sobre ese parámetro va a devolver exclusivamente un elemento. Además, así se evita la iteración sobre todo el arreglo.</p><h3 id="-gracias-por-tu-tiempo-"><strong><strong><strong>¡</strong></strong>Gracias por tu tiempo!</strong></h3><p>Si te ha resultado útil, comparte este artículo con amigos y compañeros.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Análisis de datos con pandas: Como eliminar una lista de filas de un DataFrame de pandas ]]>
                </title>
                <description>
                    <![CDATA[ Un DataFrame (marco de datos) de pandas es una estructura de datos bidimensional que permite almacenar información en forma de filas y columnas. Es una estructura muy útil para realizar análisis de datos. Dependiendo del modelo o del objetivo de tu estudio, es posible que necesites eliminar un grupo específico ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/eliminar-la-lista-de-filas-del-dataframe-de-pandas/</link>
                <guid isPermaLink="false">6357dcd92b42f608ea5efe9c</guid>
                
                    <category>
                        <![CDATA[ análisis de datos ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Felipe Navarro ]]>
                </dc:creator>
                <pubDate>Wed, 30 Nov 2022 18:34:15 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2022/10/cut_lemons--1-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/drop-list-of-rows-from-pandas-dataframe/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Data Analytics with Pandas – How to Drop a List of Rows from a Pandas Dataframe</a>
      </p><p>Un DataFrame <em>(marco de datos)</em> de pandas es una estructura de datos bidimensional que permite almacenar información en forma de filas y columnas. Es una estructura muy útil para realizar análisis de datos.</p><p>Dependiendo del modelo o del objetivo de tu estudio, es posible que necesites eliminar un grupo específico de filas del DataFrame.</p><p>En este tutorial veremos como eliminar una lista de filas de un DataFrame de pandas.</p><h2 id="como-eliminar-una-fila-o-una-columna-de-un-dataframe-de-pandas">Como eliminar una fila o una columna de un DataFrame de pandas</h2><p>Para eliminar una fila o una columna de un DataFrame, necesitas el método <code>drop()</code> del DataFrame. Puedes leer más acerca del método <code>drop()</code> en la &nbsp;<a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.drop.html">documentación</a>.</p><p><strong>Ejes del DataFrame</strong></p><ul><li>Las filas se denotan mediante <code>axis=0</code></li><li>Las columnas se denotan mediante <code>axis=1</code></li></ul><p><strong>Etiquetas del DataFrame</strong></p><ul><li>Las filas se etiquetan, por defecto, mediante un índice numérico, comenzando por el 0.</li><li>Las columnas se etiquetan por nombre.</li></ul><p><strong>Parámetros del método drop()</strong></p><ul><li><code>index</code> - la lista de filas a eliminar</li><li><code>axis=0</code> - indica que son filas, y no columnas, lo que hay que eliminar</li><li><code>inplace=True</code> - realiza la operación sobre el mismo DataFrame, en lugar de crear y devolver uno nuevo.</li></ul><h3 id="dataframe-de-muestra">DataFrame de muestra</h3><p>Nuestro DataFrame de muestra contiene las columnas, <em>nombre_producto</em>, <em>precio_unitario, num_de_unidades, cantidad_disponible</em> y d<em>isponible_desde_fecha</em>. El valor NaN se usa para denotar valores nulos.</p><pre><code class="language-python">import pandas as pd

data = {"nombre_producto":["Teclado","Raton", "Monitor", "CPU","CPU", "Altavoces",pd.NaT],
        "precio_unitario":[500, 200, 5000.235, 10000.550, 10000.550, 250.50,None],
        "num_de_unidades":[5, 5, 10, 20, 20, 8, pd.NaT],
        "cantidad disponible":[5, 6, 10, "no disponible", "no disponible", pd.NaT, pd.NaT],
        "disponible_desde_fecha":['5/11/2021', '23/4/2021', '21/08/2021', '18/09/2021', '18/09/2021', '05/01/2021', pd.NaT]
       }

df = pd.DataFrame(data)

df
</code></pre><p>El DataFrame tendrá el siguiente aspecto:</p><!--kg-card-begin: html--><table class="dataframe" border="1">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>nombre_producto</th>
      <th>precio_unitario</th>
      <th>num_de_unidades</th>
      <th>cantidad_disponible</th>
      <th>disponible_desde_fecha</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>Teclado</td>
      <td>500.000</td>
      <td>5</td>
      <td>5</td>
      <td>5/11/2021</td>
    </tr>
    <tr>
      <th>1</th>
      <td>Raton</td>
      <td>200.000</td>
      <td>5</td>
      <td>6</td>
      <td>23/4/2021</td>
    </tr>
    <tr>
      <th>2</th>
      <td>Monitor</td>
      <td>5000.235</td>
      <td>10</td>
      <td>10</td>
      <td>21/08/2021</td>
    </tr>
    <tr>
      <th>3</th>
      <td>CPU</td>
      <td>10000.550</td>
      <td>20</td>
      <td>no disponible</td>
      <td>18/09/2021</td>
    </tr>
    <tr>
      <th>4</th>
      <td>CPU</td>
      <td>10000.550</td>
      <td>20</td>
      <td>no disponible</td>
      <td>18/09/2021</td>
    </tr>
    <tr>
      <th>5</th>
      <td>Altavoces</td>
      <td>250.500</td>
      <td>8</td>
      <td>NaT</td>
      <td>05/01/2021</td>
    </tr>
    <tr>
      <th>6</th>
      <td>NaT</td>
      <td>NaN</td>
      <td>NaT</td>
      <td>NaT</td>
      <td>NaT</td>
    </tr>
  </tbody>
</table><!--kg-card-end: html--><p>Después de cada operación de eliminación, imprimiremos el DataFrame médiate <code>df</code> con el formato de tabla de <code>HTML</code>.</p><p>A continuación veremos distintas formas de seleccionar las filas a eliminar.</p><h2 id="como-eliminar-una-lista-de-filas-mediante-ndice">Como eliminar una lista de filas mediante índice</h2><p>Se puede eliminar una serie de filas pasándole al método<code>drop()</code> una lista con los índices.</p><pre><code class="language-python">df.drop([5,6], axis=0, inplace=True)

df
</code></pre><p>En este fragmento,</p><ul><li><code>[5,6]</code> son los índices de las filas a eliminar.</li><li><code>axis=0</code> denota que son filas lo que hay que eliminar</li><li><code>inplace=True</code> realiza la operación sobre el mismo DataFrame</li></ul><p>Tras eliminar las filas con índices 5 y 6, los datos en el DataFrame serán:</p><!--kg-card-begin: html--><table class="dataframe" border="1">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>nombre_producto</th>
      <th>precio_unitario</th>
      <th>num_de_unidades</th>
      <th>cantidad_disponible</th>
      <th>disponible_desde_fecha</th>
    </tr>
  </thead>
  <tbody>
     <tr>
      <th>0</th>
      <td>Teclado</td>
      <td>500.000</td>
      <td>5</td>
      <td>5</td>
      <td>5/11/2021</td>
    </tr>
    <tr>
      <th>1</th>
      <td>Raton</td>
      <td>200.000</td>
      <td>5</td>
      <td>6</td>
      <td>23/4/2021</td>
    </tr>
    <tr>
      <th>2</th>
      <td>Monitor</td>
      <td>5000.235</td>
      <td>10</td>
      <td>10</td>
      <td>21/08/2021</td>
    </tr>
    <tr>
      <th>3</th>
      <td>CPU</td>
      <td>10000.550</td>
      <td>20</td>
      <td>no disponible</td>
      <td>18/09/2021</td>
    </tr>
    <tr>
      <th>4</th>
      <td>CPU</td>
      <td>10000.550</td>
      <td>20</td>
      <td>no disponible</td>
      <td>18/09/2021</td>
    </tr>
  </tbody>
</table><!--kg-card-end: html--><h2 id="como-eliminar-filas-mediante-un-intervalo-de-ndices">Como eliminar filas mediante un intervalo de índices</h2><p>También se puede eliminar una serie de filas en un intervalo específico.</p><p>Esto puede ser útil para crear una muestra de nuestro conjunto de datos excluyendo intervalos específicos de datos.</p><p>Se puede crear un intervalo de filas en un DataFrame mediante el método <code>df.index()</code>, pasándolo luego al método <code>drop()</code> para eliminar esas filas, como se muestra a continuación:</p><pre><code class="language-python">df.drop(df.index[2:4], inplace=True)

df
</code></pre><p>Qué está haciendo este código:</p><ul><li><code>df.index[2:4]</code> genera un intervalo de filas desde la 2ª hasta la 3ª. El límite inferior es inclusivo, mientras que el superior es exclusivo. Es decir, que serán eliminadas las filas 2 y 3, mientras que la 4ª <em>no </em>será eliminada.</li><li><code>inplace=True</code> realiza la operación de eliminación sobre el mismo DataFrame.</li></ul><p>Después de eliminar filas en el intervalo 2-4, el DataFrame queda de la siguiente manera:</p><!--kg-card-begin: html--><table class="dataframe" border="1">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>nombre_producto</th>
      <th>precio_unitario</th>
      <th>num_de_unidades</th>
      <th>cantidad_disponible</th>
      <th>disponible_desde_fecha</th>
    </tr>
  </thead>
  <tbody>
     <tr>
      <th>0</th>
      <td>Teclado</td>
      <td>500.00</td>
      <td>5</td>
      <td>5</td>
      <td>5/11/2021</td>
    </tr>
    <tr>
      <th>1</th>
      <td>Raton</td>
      <td>200.00</td>
      <td>5</td>
      <td>6</td>
      <td>23/4/2021</td>
    </tr>
    <tr>
      <th>4</th>
      <td>CPU</td>
      <td>10000.55</td>
      <td>20</td>
      <td>no disponible</td>
      <td>18/09/2021</td>
    </tr>
  </tbody>
</table><!--kg-card-end: html--><h2 id="como-eliminar-todas-las-filas-despu-s-de-un-ndice">Como eliminar todas las filas después de un índice</h2><p>Es posible eliminar todas las filas posteriores a un índice determinado mediante <code>iloc[]</code>.</p><p>Con el método <code>iloc[]</code> se seleccionan las filas mediante índices, especificando las posiciones inicial y final separadas por <code>:</code>. Por ejemplo, ya hemos usado <code>2:4</code> para seleccionar las filas 2 y 3. Si las queremos seleccionar todas, simplemente pasamos <code>:</code> a <code>iloc[]</code>.</p><p>Esto resulta útil en los casos en los que se quiera dividir el conjunto de datos con propósitos de prueba.</p><p>El siguiente fragmento selecciona las filas con índices 0 y 1 y lo asigna a la misma variable. El resultado final es la eliminación de todas las filas a partir del índice 2.</p><pre><code class="language-python">df = df.iloc[:2]

df
</code></pre><p>Con <code>:2</code> se seleccionan las filas hasta el índice 2 (exclusivo).</p><p>Después de esta operación, nuestro DataFrame tendrá el siguiente aspecto:</p><!--kg-card-begin: html--><table class="dataframe" border="1">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>nombre_producto</th>
      <th>precio_unitario</th>
      <th>num_de_unidades</th>
      <th>cantidad_disponible</th>
      <th>disponible_desde_fecha</th>
    </tr>
  </thead>
  <tbody>
     <tr>
      <th>0</th>
      <td>Teclado</td>
      <td>500.0</td>
      <td>5</td>
      <td>5</td>
      <td>5/11/2021</td>
    </tr>
    <tr>
      <th>1</th>
      <td>Raton</td>
      <td>200.0</td>
      <td>5</td>
      <td>6</td>
      <td>23/4/2021</td>
    </tr>
  </tbody>
</table><!--kg-card-end: html--><h2 id="com-eliminar-filas-usando-m-ltiples-condiciones">Com eliminar filas usando múltiples condiciones</h2><p>En lugar de especificar unas filas concretas mediante índices, es posible seleccionar las filas que cumplan unas determinadas condiciones.</p><p>Por ejemplo, podrías eliminar filas cuyo valor en alguna de las columnas fuera mayor que <em>X</em> y menor que <em>Y</em>.</p><p>Esto puede ser útil en el caso de que quieras crear un conjunto de datos que ignore unos valores específicos en ciertas columnas.</p><p>Para eliminar filas condicionalmente, selecciona los índices de las filas que cumplan la condición, pasándolos luego al método <code>drop()</code>.</p><pre><code class="language-python">df.drop(df[(df['precio_unitario'] &gt;400) &amp; (df['precio_unitario'] &lt; 600)].index, inplace=True)

df
</code></pre><p>En el código anterior,</p><ul><li><code>(df['Unit_Price'] &gt;400) &amp; (df['Unit_Price'] &lt; 600)</code> es la condición para eliminar las filas.</li><li><code>df[].index</code> selecciona los índices de las filas que cumplen la condición.</li><li><code>inplace=True</code> realiza la operación de eliminado sobre el mismo DataFrame, en lugar de crear y devolver uno nuevo.</li></ul><p>Después de eliminar las filas que cumplen la condición de tener <code>precio_unitario</code> mayor que 400 y menor que 600, nuestro DataFrame quedará con los siguientes datos:</p><!--kg-card-begin: html--><table class="dataframe" border="1">
   <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>nombre_producto</th>
      <th>precio_unitario</th>
      <th>num_de_unidades</th>
      <th>cantidad_disponible</th>
      <th>disponible_desde_fecha</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>1</th>
      <td>Raton</td>
      <td>200.0</td>
      <td>5</td>
      <td>6</td>
      <td>23/4/2021</td>
    </tr>
  </tbody>
</table><!--kg-card-end: html--><h2 id="conclusi-n">Conclusión</h2><p>En resumen, en este artículo nos hemos familiarizado con el método <code>drop()</code> de los DataFrame de pandas. También hemos visto como se etiquetan las filas y columnas de los DataFrame. Y finalmente hemos aprendido a eliminar filas mediante índices, un intervalo de índices y basándose en condiciones.</p><p>Si te ha gustado este artículo, no dudes en compartirlo.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Tutorial JVM - La arquitectura de la máquina virtual de Java explicada para principiantes ]]>
                </title>
                <description>
                    <![CDATA[ Tanto si has programado en Java como si no, seguramente habrás escuchado hablar de la Máquina Virtual de Java (en inglés Java Virtual Machine, JVM) en algún momento. JVM es el núcleo del ecosistema Java, permitiendo al software basado en esta tecnología seguir el enfoque "escríbelo (tu programa) una sola ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/tutorial-jvm-la-arquitectura-de-la-maquina-virtual-de-java-explicada-para-principiantes/</link>
                <guid isPermaLink="false">63403e99d632c3088e4f264f</guid>
                
                    <category>
                        <![CDATA[ java ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Felipe Navarro ]]>
                </dc:creator>
                <pubDate>Mon, 28 Nov 2022 19:26:13 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2022/10/JVM-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/jvm-tutorial-java-virtual-machine-architecture-explained-for-beginners/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">JVM Tutorial - Java Virtual Machine Architecture Explained for Beginners</a>
      </p><p>Tanto si has programado en Java como si no, seguramente habrás escuchado hablar de la Máquina Virtual de Java (en inglés <em>Java Virtual Machine</em>, <strong>JVM</strong>) en algún momento.</p><p>JVM es el núcleo del ecosistema Java, permitiendo al software basado en esta tecnología seguir el enfoque <em>"escríbelo </em>(tu programa)<em> una sola vez, ejecútalo en cualquier parte (write once, run anywhere)"</em>. Puedes escribir código Java en un tipo de máquina concreto, y ejecutarlo en cualquier otro tipo de máquina usando la JVM.</p><p>Inicialmente, la JVM fue diseñada para admitir Java solamente. Pero, con el paso de los años, muchos otros lenguajes como Scala, Kotlin y Groovy fueron adoptados por la plataforma Java. El conjunto de estos lenguajes se conoce como lenguajes JVM.</p><p>En este artículo aprenderemos las esencias de la JVM, cómo funciona y los componentes en que se divide.</p><h1 id="-qu-es-una-m-quina-virtual">¿Qué es una máquina virtual?</h1><p>Antes de entrar de lleno en la JVM, revisemos el concepto de máquina virtual (VM).</p><p>Una máquina virtual es la <em>representación virtual de un ordenador físico</em>. Normalmente, se llama huésped (<em>guest</em>) a la máquina virtual, mientras que al ordenador físico en que se ejecuta, se le suele llamar anfitrión (<em>host</em>).</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2022/10/primera_dos.png" class="kg-image" alt="image-37" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2022/10/primera_dos.png 600w, https://www.freecodecamp.org/espanol/news/content/images/2022/10/primera_dos.png 800w" sizes="(min-width: 720px) 720px" width="800" height="536" loading="lazy"></figure><p>Una sola máquina física puede ejecutar varias máquinas virtuales, cada una con su propio sistema operativo y aplicaciones a nivel de usuario; están aisladas unas de otras.</p><h1 id="-qu-es-la-m-quina-virtual-de-java">¿Qué es la Máquina Virtual de Java?</h1><p>En lenguajes de programación como C o C++, el código es compilado al código máquina específico de esa platoforma en concreto: son <em>lenguajes compilados</em>.</p><p>Por otro lado, en lenguajes como JavaScript o Python, el ordenador ejecuta las instrucciones directamente sin tener que compilarlas: son <em>lenguajes interpretados.</em></p><p>Java usa una combinación de ambas técnicas. El código es compilado a bytecode (un formato binario independiente del hardware y del sistema operativo, que representa instrucciones de la JVM) generando un fichero con formato <em>class</em>. Este fichero<em> class </em>es interpretado por la JVM en la plataforma anfitriona. Un mismo fichero <em>class </em>puede ser ejecutado por la JVM en cualquier plataforma y sistema operativo.</p><p><em>De manera similar a las máquinas virtuales,</em> la JVM crea un espacio aislado en la máquina anfitriona. Este espacio se usa para ejecutar programas Java sea cual sea la plataforma o el sistema operativo de dicha máquina.</p><h1 id="arquitectura-de-la-m-quina-virtual-de-java">Arquitectura de la Máquina Virtual de Java</h1><p>La JVM consta de tres componentes:</p><ol><li>Cargador de clases (<em>Class Loader</em>)</li><li>Área de datos/memoria en tiempo de ejecución (<em>Runtime Memory/Data Area)</em></li><li>Motor de ejecución (<em>Execution Engine</em>)</li></ol><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2022/10/figura2.png" class="kg-image" alt="image-39" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2022/10/figura2.png 600w, https://www.freecodecamp.org/espanol/news/content/images/2022/10/figura2.png 725w" sizes="(min-width: 720px) 720px" width="725" height="388" loading="lazy"></figure><p>Echemos un vistazo a cada uno de ellos.</p><h2 id="cargador-de-clases">Cargador de clases</h2><p>Como resultado de la compilación del código fuente almacenado en un fichero<code>.java</code>, se obtiene bytecode almacenado en un fichero <code>.class</code> . Si en un programa se va a hacer uso de esta clase, será cargado en memoria principal por el cargador de clases.</p><p>La primera clase en ser cargada en memoria es, normalmente, aquella que contiene el método <code>main()</code> .</p><p>El proceso de carga de clases consta de tres fases: carga (<em>loading</em>), enlazado (<em>linking</em>), e inicialización (<em>initialization</em>).</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2022/10/figura3-1.png" class="kg-image" alt="image-40" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2022/10/figura3-1.png 600w, https://www.freecodecamp.org/espanol/news/content/images/2022/10/figura3-1.png 620w" width="620" height="309" loading="lazy"></figure><h3 id="carga-loading-">Carga <em>(loading)</em></h3><p>La fase de carga consiste en encontrar la representación binaria (bytecode) de una clase o interfaz con un nombre concreto, y crear una clase o interfaz a partir de dicha representación (<em>crear</em> una clase o interfaz <em>c</em> es construir una representación interna, específica de esa implementación de la JVM, de <em>c</em>).</p><p>Hay tres cargadores de clases incorporados:</p><ul><li><strong>Cargador de clases de arranque (</strong><em><strong>Bootstrap Class Loader</strong></em><strong>)</strong> <strong>-</strong> raíz de la jerarquía de cargadores de clases, superclase de Extension Class Loader. Carga los paquetes estándar de Java como <code>java.lang</code>, <code>java.net</code>, <code>java.util</code>, <code>java.io</code>, etc. localizados en el fichero <code>rt.jar</code> y otras bibliotecas fundamentales presentes en el directorio <code>$JAVA_HOME/jre/lib</code> .</li><li><strong>Cargador de clases de extensión (</strong><em><strong>Extension Class Loader</strong></em><strong>) -</strong> subclase de Bootstrap Class Loader y superclase de Application Class Loader. Carga las extensiones de las bibliotecas estándar de Java presentes en el directorio <code>$JAVA_HOME/jre/lib/ext</code> .</li><li><strong>Cargador de clases de aplicación (<em>Application Class Loader</em>) -</strong> es el cargador de clases en el nivel más bajo de la jerarquía, subclase de Extension Class Loader. Carga los ficheros indicados en el <em>classpath</em> (variable de entorno que almacena la ruta a las clases creadas por el usuario). Por defecto, la variable classpath es establecida al directorio actual de la aplicación; puede ser modificada desde la línea de comandos con la opción <code>-classpath</code> o <code>-cp</code> (al ejecutar <code>java</code> o <code>javac</code> , por ejemplo).</li></ul><p>La JVM usa el método <code>ClassLoader.loadClass()</code> para cargar una clase en memoria, haciendo uso del <em>nombre binario </em>de la clase.</p><p>Si un cargador de clases es incapaz de encontrar una clase, delega el trabajo en el cargador de una subclase suya. Si el último cargador de la jerarquía tampoco es capaz de encontrar la clase en cuestión, se producirá <code>NoClassDefFoundError</code> o <code>ClassNotFoundException</code><em>.</em></p><h3 id="enlazado-linking-">Enlazado <em>(linking)</em></h3><p>Después de que una clase haya sido cargada en memoria, se somete al proceso de enlazado. Enlazar una clase o una interfaz supone resolver las referencias externas y dependencias, integrando la clase en el conjunto del programa que hace uso de ella.</p><p>El enlazado incluye los siguientes pasos:</p><p><strong>Verificación:</strong> esta fase verifica la corrección estructural del archivo<code>.class</code> contrastándolo frente a un conjunto de restricciones o reglas. Si la verificación falla, se produce <code>VerifyException</code>.</p><p>Por ejemplo, si el código se ha construído con Java 11, pero se va a ejecutar en un sistema con Java 8, la fase de verificación fallará.</p><p><strong>Preparación:</strong> en esta fase, la JVM asigna memoria para los campos estáticos de una clase o interfaz, inicializándolos con valores por defecto.</p><p>Supón, como ejemplo, que has declarado en una clase la siguiente variable:</p><pre><code class="language-java">private static final boolean activado = true;</code></pre><p>Durante la fase de preparación, la JVM asigna memoria para la variable <code>activado</code> y le asigna el valor por defecto para un booleano, que es <code>false</code>.</p><p><strong>Resolución:</strong> es el proceso de resolver dinámicamente las referencias simbólicas presentes en el almacén de constantes de tiempo de ejecución (<em>runtime constant pool, </em>una estructura de datos del fichero <code>.class</code>).</p><p>Las referencias (simbólicas) que dentro de una clase se hacen a otras clases o a constantes presentes en otras clases, son resueltas en esta etapa asignándoles los valores reales.</p><h3 id="inicializaci-n-initialization-">Inicialización <em>(initialization)</em></h3><p>La inicialización consiste en ejecutar <code>&lt;clinit&gt;</code>, el método de inicialización de una clase o interfaz. En esta etapa se ejecutan los bloques de inicialización estáticos y se asignan los valores a las variables estáticas. Es el paso final del proceso de carga de clases.</p><p>Por ejemplo, cuando anteriormente hemos declarado el siguiente código:</p><pre><code class="language-java">private static final boolean activado = true;</code></pre><p>La variable <code>activado</code> fue establecida con su valor por defecto, <code>false</code> , durante la fase de preparación. Ahora, en la fase de inicialización, se le asigna el valor real que queríamos darle, <code>true</code>.</p><p><strong>Nota:</strong> la JVM es multihilo. Cabe la posibilidad de que múltiples hilos intenten inicializar la misma clase al mismo tiempo, provocando problemas de concurrencia. Hay que gestionar cada hilo de forma segura para garantizar que el programa funcione adecuadamente en un entorno multihilo.</p><h2 id="-rea-de-datos-en-tiempo-de-ejecuci-n">Área de datos en tiempo de ejecución</h2><p>El área de datos en tiempo de ejecución está formado por cinco componentes:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2022/10/figura4-1.png" class="kg-image" alt="image-32" width="586" height="291" loading="lazy"></figure><p>Veamos cada componente por separado.</p><h3 id="-rea-de-m-todos">Área de métodos</h3><p>Todos los datos a nivel de clase, como el runtime constant pool, datos de los campos y los métodos, así como el código de los métodos y constructores, son almacenados en esta área.</p><p>Si la memoria disponible en el área de métodos no puede satisfacer una petición de asignación de memoria por parte de un proceso, la JVM emite un <code>OutOfMemoryError</code>.</p><p>Supongamos que has definido la siguiente clase:</p><pre><code class="language-java">public class Empleado {
  
  private String nombre;
  private int edad;
  
  public Empleado(String nombre, int edad) {
  
    this.nombre = nombre;
    this.edad = edad;
  }
}</code></pre><p>Los datos de los campos <code>nombre</code> y <code>edad</code> y el código del constructor son guardados en el área de métodos.</p><p>El área de métodos se crea al arrancar la JVM y es compartida por todos los hilos de ejecución.</p><h3 id="area-del-mont-culo-heap-">Area del montículo <em>(heap)</em></h3><p>Todos los objetos y sus correspondientes variables de instancia son almacenados en esta zona. El montículo es el área de datos de tiempo de ejecución en la que se aloja la memoria asignada a los arrelgos e instancias de clases.</p><p>Supongamos que se ha declarado la siguiente instancia:</p><pre><code class="language-java">Employee empleado = new Empleado();</code></pre><p>En este ejemplo, se crea una instancia de la clase <code>Empleado</code> , que será cargada en memoria en el área del montículo.</p><p>Al igual que el área de métodos, el área del montículo es creada al arrancar la JVM, y se comparte por todos los hilos.</p><p><strong>Nota:</strong> como las áreas del montículo y de métodos comparten la misma memoria para los diferentes hilos, habrá que gestionar cada hilo de forma segura para asegurar la integridad de los datos, como ya comentábamos en el apartado de inicialización de clases.</p><h3 id="area-de-pilas-stack-">Area de pilas <em>(stack)</em></h3><p>A cada hilo creado en la JVM le corresponde en exclusiva una pila, creada al mismo tiempo que el propio hilo. Las variables locales, resultados parciales y llamadas a métodos se almacenan en esta zona de memoria conocida como pila.</p><p>Si el procesamiento que se está llevando a cabo en un hilo requiere un tamaño de pila mayor del permitido, la JVM emite un <code>StackOverflowError</code>.</p><p>Para cualquier llamada a método, se genera en la memoria de pila una entrada llamada marco de pila (<em>stack frame</em>). Cuando se completa la llamada al método, el marco de pila es destruido.</p><p>El marco de pila se divide en tres partes:</p><ul><li><strong>Variables locales –</strong> cada marco contiene un arreglo donde se almacenan las variables locales y sus valores. La longitud de este arreglo se establece en tiempo de compilación.</li><li><strong>Pila de operandos </strong><em>(operand stack)</em> <strong>–</strong> esta estructura de tipo pila es utilizada para llevar a cabo las operaciones intermedias durante la llamada al método en cuestión. La profundidad máxima de esta pila se determina también en tiempo de compilación.</li><li><strong>Marco de datos </strong><em>(frame data)</em><strong> – </strong>aquí se guardan todos los símbolos del método invocado, así como la información del bloque <em>catch</em> en caso de que se produzca alguna excepción.</li></ul><p>Supongamos el siguiente código:</p><pre><code class="language-java">double calcularPuntuacionNormalizada(List&lt;Respuesta&gt; respuestas) {
  
  double puntuacion = getPuntuacion(respuestas);
  normalizarPuntuacion(puntuacion);
}

normalizarPuntuacion(double puntuacion) {
  
  return (puntuacion – minPuntuacion) / (maxPuntuacion – minPuntuacion);
}
</code></pre><p>En este ejemplo, el arreglo de variables locales contendrá las variables <code>respuestas</code> y <code>puntuacion</code>. La pila de operandos contiene las variables y operadores necesarios para realizar las operaciones de sustracción y división.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2022/10/figura5.png" class="kg-image" alt="image-36" width="467" height="236" loading="lazy"></figure><p><strong>Nota:</strong> como cada pila es exclusiva de un hilo, esta área de memoria es inherentemente segura en ambiente multihilo.</p><h3 id="registros-de-contador-de-programa-pc-program-counter-">Registros de contador de programa <em>(PC, program counter)</em></h3><p>La JVM admite múltiples hilos simultáneamente. Cada hilo tiene su propio registro contador de programa (PC) para guardar la dirección de la instrucción de la JVM ejecutándose en ese momento. Una vez ejecutada dicha instrucción, el registro PC es actualizado con la dirección de la próxima instrucción.</p><h3 id="pilas-para-m-todos-nativos">Pilas para métodos nativos</h3><p>La JVM puede hacer uso de pilas que soporten métodos <em>nativos</em>, métodos escritos en lenguajes diferentes a Java, como C o C++. Cada hilo posee su propia pila de métodos nativos.</p><h2 id="motor-de-ejecuci-n">Motor de ejecución</h2><p>Una vez que el bytecode se ha cargado en memoria y la información necesaria está disponible en el área de datos de tiempo de ejecución, el siguiente paso es ejecutar el programa. El motor de ejecución gestiona este proceso ejecutando el código de cada clase.</p><p>Sin embargo, antes de ejecutar el programa, hay que traducir el bytecode a instrucciones del lenguaje máquina, usando un intérprete o un compilador JIT.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2022/10/figura6.png" class="kg-image" alt="image-33" width="578" height="354" loading="lazy"></figure><h3 id="int-rprete">Intérprete</h3><p>El intérprete lee y ejecuta las instrucciones del bytecode línea a línea. Debido a esta ejecución línea por línea, el intérprete es comparativamente más lento.</p><p>Otra desventaja es la reinterpretación de un método cada vez que es llamado.</p><h3 id="compilador-jit">Compilador JIT</h3><p>El compilador JIT salva las desventajas del intérprete. En primera instancia, el motor de ejecución usa el intérprete para ejecutar el bytecode, entrando en acción el compilador JIT cuando se encuentra código repetido.</p><p>El compilador JIT compila el bytecode traduciéndolo a código máquina nativo, que es usado directamente en las reiteradas llamadas a métodos, mejorando así el rendimiento del sistema.</p><p>El compilador JIT se divide en los siguientes componentes:</p><ol><li><strong>Generador de código intermedio</strong></li><li><strong>Optimizador de código -</strong> optimiza el código intermedio para un mejor desempeño</li><li><strong>Generador de código objetivo -</strong> traduce el código intermedio en código máquina nativo</li><li><strong>Perfilador </strong><em><strong>(profiler)</strong></em><strong> -</strong> encuentra los <em>HotSpots</em> (código que es ejecutado repetidamente)</li></ol><p>Veamos el siguiente código para ilustrar la diferencia entre el intérprete y el compilador JIT:</p><pre><code class="language-java">int sum = 10;
for(int i = 0 ; i &lt;= 10; i++) {
   sum += i;
}
System.out.println(sum);</code></pre><p>Un intérprete busca en memoria el valor de <code>sum</code> en cada iteración del bucle, le suma el valor de<code>i</code>, y lo vuelve a almacenar en la memoria. Es una operación costosa, ya que se está accediendo a memoria en cada iteración.</p><p>Sin embargo, el compilador JIT reconoce que este código tiene un HotSpot, y realizará optimizaciones sobre él. Creará una copia local de <code>sum</code> en el registro PC del hilo, sumándole el valor de <code>i</code> en cada vuelta del bucle y, una vez concluído, llevará el nuevo valor de <code>sum</code> a la memoria.</p><p><strong>Nota:</strong> un compilador JIT tarda más en compilar el código que un intérprete en interpretarlo línea por línea. Si se va a ejecutar el programa solo una vez, es mejor usar el intérprete.</p><h3 id="recolector-de-basura-gc-garbage-collector-">Recolector de basura <em>(GC, garbage collector)</em></h3><p>El recolector de basura detecta y elimina objetos no referenciados en el área del heap. Es el proceso de recuperar automáticamente, en tiempo de ejecución, la memoria ocupada por objetos que ya no van a ser utilizados, mediante la destrucción de tales objetos.</p><p>La recolección de basura hace que Java sea eficiente desde el punto de vista de la gestión de memoria, ya que libera memoria del área heap eliminando objetos no referenciados, creándose así espacio para nuevos objetos. Este proceso implica dos fases:</p><ol><li><strong>Marcado -</strong> identificación de objetos no referenciados</li><li><strong>Barrido -</strong> destrucción de los objetos identificados en el paso anterior</li></ol><p>La JVM realiza automáticamente la recolección de basura a intervalos regulares, no siendo necesaria su gestión separadamente. Puede ser disparada invocando <code>System.gc()</code>, aunque la ejecución no está garantizada.</p><p>La JVM tiene tres tipos de recolectores de basura:</p><ol><li><strong>En serie -</strong> es la implementación más simple, diseñada para pequeñas aplicaciones ejecutándose en entornos monohilo. Usando un solo hilo, produce un evento de tipo "parar el mundo" en el que todos los hilos de aplicación son detenidos hasta que la operación se complete. El argumento de la JVM para usar recolección de basura en serie es <code>-XX:+UseSerialGC</code></li><li><strong>En paralelo - </strong>es la implementación por defecto en la JVM, conocido como recolector de rendimiento <em>(throughput collector)</em>. Uitiliza múltiples hilos, pero aún necesita parar los hilos de aplicación. El argumento de la JVM es <code>-XX:+UseParallelGC</code>.</li><li><strong>Garbage First (G1) GC -</strong> G1GC fue diseñado para aplicaciones multihilo con gran cantidad disponible de heap (más de 4GB). Particiona el heap en un conjunto de regiones de igual tamaño, utilizando múltiples hilos para explorarlas. G1GC identifica las regiones con el máximo de basura y realiza la limpieza prioritaria de esas regiones. El argumento de la JVM para G1GC es <code>-XX:+UseG1GC</code></li></ol><p><strong>Nota:</strong> hay otro tipo de colector de basura llamado <strong>Barrido de Marcas Concurrente</strong> <strong><em>(Concurrent Mark Sweep (CMS) GC)</em></strong>. Sin embargo, fue declarado obsoleto en Java 9 y completamente eliminado en Java 14 en favor de G1GC.</p><h2 id="interfaz-nativa-de-java-jni-">Interfaz nativa de Java (JNI)</h2><p>En ocasiones, es necesario utilizar código nativo en lugar de Java (por ejemplo, C/C++). Esas ocasiones pueden ser cuando necesitamos interactuar con el hardware, o salvar las restricciones de Java en cuanto a gestión de memoria y rendimiento. Java admite la ejecución de código nativo a través de la Interfaz Nativa de Java (JNI).</p><p>JNI hace de puente permitiendo el uso de paquetes de apoyo para otros lenguajes, como C, C++, etc. Esto resulta de mucha ayuda en casos en que se necesita escribir código que no esté enteramente admitido por Java, como ciertas características específicas de la plataforma subyacente que solo pueden ser escritas en C.</p><p>La palabra reservada <code>native</code> indica que la implementación del método será proporcionada por una biblioteca nativa. Es necesario invocar <code>System.loadLibrary()</code> para cargar en memoria dicha biblioteca nativa compartida y tener su funcionalidad disponible en Java.</p><h2 id="bibliotecas-de-m-todos-nativos">Bibliotecas de métodos nativos</h2><p>Las bibliotecas de métodos nativos son bibliotecas escritas en otros lenguajes, como C, C++ y ensamblador, normalmente en archivos de extensión <code>.dll</code> o <code>.so</code>. Pueden ser cargadas a través de JNI.</p><h1 id="errores-habituales-de-la-jvm">Errores habituales de la JVM</h1><ul><li><strong>ClassNotFoundException</strong> - ocurre cuando el cargador de clases intenta cargar clases mediante <code>Class.forName()</code>, <code>ClassLoader.loadClass()</code> o <code>ClassLoader.findSystemClass()</code> pero no se encuentra la definición de la clase con el nombre especificado.</li><li><strong>NoClassDefFoundError</strong> - se produce cuando la compilación de la clase ha tenido éxito, pero el cargador de clases no es capaz de encontrar el fichero tipo class en tiempo de ejecución.</li><li><strong>OutOfMemoryError</strong> - la JVM no puede asignar memoria para un objeto, ya que no hay suficiente y el recolector de basura no es capaz de proporcionar más memoria.</li><li><strong>StackOverflowError</strong> - la JVM se queda sin espacio al crear nuevos marcos de pila.</li></ul><h1 id="conclusi-n">Conclusión</h1><p>En este artículo hemos discutido la arquitectura de la Máquina Virtual de Java y sus diversos componentes. Lo habitual es no preocuparse demasiado de su mecánica interna ni de su funcionamiento mientras nuestro código se ejecuta con normalidad.</p><p>Solo cuando algo va mal, y necesitamos ajustar la JVM o corregir un fallo de memoria, intentamos comprender su funcionamiento interno.</p><p>Es una cuestión muy popular en entrevistas de trabajo, tanto a nivel junior como senior para perfiles backend. Tener amplios conocimientos de la JVM te ayudará a producir mejor código y evitar trampas que conduzcan a errores de pila o de memoria.</p><figure class="kg-card kg-embed-card" data-test-label="fitted">
        <div class="fluid-width-video-container">
          <div style="padding-top: 56.25%;" class="fluid-width-video-wrapper">
            <iframe src="https://www.youtube.com/embed/jnpuRvRdTgI?feature=oembed" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" title="Embedded content" loading="lazy" name="fitvid0" frameborder="0" width="256" height="144"></iframe>
          </div>
        </div>
      </figure><p>Gracias por acompañarme hasta tan lejos. Espero que te haya gustado el artículo. Puedes encontrarme en <a href="https://www.linkedin.com/in/theawesomenayak/">LinkedIn</a>, donde normalmente hablo sobre tecnología y sobre la vida. Echa también un vistazo a <a href="https://www.freecodecamp.org/news/author/theawesomenayak/">mis otros artículos</a> y a <a href="https://www.youtube.com/channel/UCmWAaPgfWAkl-Jep5mY-NNg">mi canal de YouTube</a>. Que disfrutes de la lectura. ?</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Tuple vs List en Python: ¿Cuál es la diferencia? ]]>
                </title>
                <description>
                    <![CDATA[ Tuplas (Tuple) y listas (List) son dos de los cuatro tipos de datos incorporados que puedes usar en Python para almacenar colecciones de datos. Los otros dos serían conjuntos (Set) y diccionarios (Dictionary). Ambos son muy útiles y pueden parecer similares tras un primer vistazo. Pero tienen diferencias significativas y ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/tuple-vs-list-en-python-cual-es-la-diferencia/</link>
                <guid isPermaLink="false">632a25d370a5cb0907d6978c</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Felipe Navarro ]]>
                </dc:creator>
                <pubDate>Fri, 21 Oct 2022 20:19:34 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2022/09/pexels-christina-morillo-1181359--1--1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/python-tuple-vs-list-what-is-the-difference/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Python Tuple VS List – What is the Difference?</a>
      </p><p>Tuplas (Tuple) y listas (List) son dos de los cuatro tipos de datos incorporados que puedes usar en Python para almacenar colecciones de datos. Los otros dos serían conjuntos (Set) y diccionarios (Dictionary).</p><p>Ambos son muy útiles y pueden parecer similares tras un primer vistazo. Pero tienen diferencias significativas y cada uno de ellos será más útil según el caso.</p><p>En este artículo vamos a dar una visión general de cómo funcionan las tuplas y las listas. Hablaremos acerca de sus características y sus casos de uso, y mostraré sus parecidos y diferencias.</p><p>Puedes probar los códigos de ejemplo mostrados en el artículo usando la shell interactiva de Python, la cual tienes disponible en tu máquina una vez instalado Python.</p><p>¡Comencemos!</p><h2 id="-qu-son-tuplas-y-listas-en-python">¿Qué son tuplas y listas en Python?</h2><p>Tuplas y Listas son estructuras de datos incorporadas en Python.</p><p>Son contenedores para el almacenamiento de una colección ordenada de uno o más elementos, accesibles mediante indexación.</p><p>Una tupla pertence a la clase 'tuple',<code>&lt;class 'tuple'&gt;</code>, mientras que una lista pertenece a la clase 'list', <code>&lt;class 'list'&gt;</code> .</p><p>Digamos que has creado una tupla llamada <code>mi_tupla</code>. Puedes comprobar su tipo de la siguiente manera:</p><pre><code class="language-python">&gt;&gt;&gt;type(mi_tupla)

#output
&lt;class 'tuple'&gt;
</code></pre><p>Esto es particularmente útil para depuración.</p><p>Veamos ahora algunas otras similitudes entre tuplas y listas.</p><h2 id="similitudes-entre-tuplas-y-listas-en-python">Similitudes entre tuplas y listas en Python</h2><p>Como ya he mencionado anteriormente, tuplas y listas son muy similares, y comparten ciertas características que veremos a continuación.</p><h3 id="tuplas-y-listas-pueden-almacenar-m-ltiples-elementos-bajo-una-nica-variable">Tuplas y listas pueden almacenar múltiples elementos bajo una única variable</h3><p>Tanto las tuplas como las listas o bien pueden estar vacías o bien pueden contener uno o incluso múltiples elementos bajo una única variable.</p><p>La única diferencia radica en la sintaxis: las tuplas se crean rodeando los elementos que va a contener mediante paréntesis, <code>()</code>, mientras que las listas se crean usando corchetes,<code>[]</code>.</p><p>Para crear una tupla <em>vacía</em>, puedes usar solo los paréntesis,<code>()</code>, o bien el método constructor <code>tuple()</code>.</p><pre><code class="language-python">&gt;&gt;&gt;type(())
&lt;class 'tuple'&gt;

&gt;&gt;&gt;mi_tupla = ()

&gt;&gt;&gt;type(mi_tupla)
&lt;class 'tuple'&gt;

#or..


&gt;&gt;&gt;mi_tupla = tuple()

&gt;&gt;&gt;type(mi_tupla)
&lt;class 'tuple'&gt;
</code></pre><p>Para crear una lista <em>vacía</em> puedes usar simplemente los corchetes o llamar al método constructor <code>list()</code>.</p><pre><code class="language-python">&gt;&gt;&gt;type([])
&lt;class 'list'&gt;


&gt;&gt;&gt;mi_lista = []

#or..

&gt;&gt;&gt;mi_lista = list()
</code></pre><p>Cuando estemos creando una tupla con solo <em>un elemento</em>, no hay que olvidarse de añadir una coma al final.</p><pre><code class="language-python">&gt;&gt;&gt;edad = (28,)
</code></pre><p>Si estás usando el método <code>tuple()</code>, serán necesarios dobles paréntesis.</p><pre><code class="language-python">&gt;&gt;&gt;edad = tuple((28,))

&gt;&gt;&gt;type(edad)
&lt;class 'tuple'&gt;
</code></pre><p>Si no añades la coma al final, Python no lo reconocerá como una tupla.</p><pre><code class="language-python">&gt;&gt;&gt;edad = (28)

&gt;&gt;&gt;type(edad)
&lt;class 'int'&gt;

&gt;&gt;&gt;edad = tuple((28))
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
TypeError: 'int' object is not iterable</code></pre><p>Se pueden crear tuplas de uno o más elementos sin utilizar los paréntesis (ojo, con el método, <code>tuple()</code> sí son necesarios):</p><pre><code class="language-python">&gt;&gt;&gt; mi_tupla = 'python',  # &lt;-- obsérvese la coma final.
&gt;&gt;&gt; type(mi_tupla)
&lt;class 'tuple'&gt;

&gt;&gt;&gt; otra_tupla = 1, 2, 3  # &lt;-- aquí no es necesaria la coma.
&gt;&gt;&gt; type(otra_tupla)
&lt;class 'tuple'&gt;
</code></pre><p>Al crear una lista con solo <em>un elemento</em>, no es necesario añadir la coma final.</p><pre><code class="language-python">&gt;&gt;&gt; edad = [28]

&gt;&gt;&gt; type(edad)
&lt;class 'list'&gt;
</code></pre><p>Los elementos almacenados son generalmente de naturaleza similar y están relacionados unos con otros de alguna manera.</p><p>Puedes crear una tupla o una lista que contenga sencillamente una secuencia de cadenas, de enteros o de valores Booleanos, estando los elementos de la secuencia separados por comas.</p><p>Se puede crear una tupla o una lista que contenga una mezcla de diferentes tipos de datos.</p><pre><code class="language-python">&gt;&gt;&gt;mi_informacion = ["Dionysia",27,True,"Lemonaki",7,"Python",False]

#or..

&gt;&gt;&gt;mi_informacion = list(("Dionysia",27,True,"Lemonaki",7,"Python",False))

print(mi_informacion)
['Dionysia', 27, True, 'Lemonaki', 7, 'Python', False]
</code></pre><p>Listas y tuplas pueden contener elementos duplicados, apareciendo múltiples veces.</p><pre><code class="language-python">&gt;&gt;&gt;informacion = ("Jimmy",50,True,"Kate",50)

&gt;&gt;&gt;print(informacion)
('Jimmy', 50, True, 'Kate', 50)

or..

&gt;&gt;&gt;mi_informacion = ["Dionysia",27,True,"Lemonaki",7,"Python",False,27,"Python",27]
</code></pre><p>Si te olvidas de las comas, obtendrás un error:</p><pre><code class="language-python">&gt;&gt;&gt;informacion = ("Jimmy" 50,True,"Kate",50)
File "&lt;stdin&gt;", line 1
    &gt;&gt;&gt;informacion = ("Jimmy" 50,True,"Kate",50)
    ^
SyntaxError: invalid syntax</code></pre><pre><code class="language-python">&gt;&gt;&gt;my_informacion = ["Dionysia" 28,True,"Lemonaki",7,"Python",False]
 File "&lt;stdin&gt;", line 1
    my_informacion = ["Dionysia" 28,True,"Lemonaki",7,"Python",False]
                                 ^
SyntaxError: invalid syntax
</code></pre><p>Para comprobar la longitud y determinar cuantos elementos hay en la tupla o en la lista, habrá que hacer uso del método <code>len()</code> .</p><pre><code class="language-python">&gt;&gt;&gt;mi_informacion = ["Dionysia",27,True,"Lemonaki",7,"Python",False,27,"Python",27]

&gt;&gt;&gt;len(mi_informacion)
7
</code></pre><h3 id="tuplas-y-listas-en-python-soportan-desempaquetado">Tuplas y Listas en Python soportan desempaquetado</h3><p>Esencialmente, cuando se crea una tupla o una lista, varios valores son 'empaquetados' en una única variable, como ya he mencionado anteriormente.</p><pre><code class="language-python">&gt;&gt;&gt;front_end = ("html","css","javascript")
</code></pre><p>Esos valores puede ser 'desempaquetados' y asignados a variables individuales.</p><pre><code class="language-python">&gt;&gt;&gt;front_end = ("html","css","javascript")

&gt;&gt;&gt;contenido,estilismo,interactividad = front_end

&gt;&gt;&gt;contenido
'html'

&gt;&gt;&gt;estilismo
'css'

&gt;&gt;&gt;interactividad
'javascript'
</code></pre><p>Hay que asegurarse de que el número de variables que creas es exactamente el mismo que la cantidad de valores de la tupla/lista, de otro modo Python lanzará un error:</p><pre><code class="language-python">&gt;&gt;&gt;front_end = ("html","css","javascript")

&gt;&gt;&gt;contenido,estilismo = front_end
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
ValueError: too many values to unpack (expected 2)


#or..


&gt;&gt;&gt;front_end = ("html","css","javascript")

&gt;&gt;&gt;contenido,estilismo,interactividad,datos =  front_end
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
ValueError: not enough values to unpack (expected 4, got 3)
</code></pre><h3 id="se-puede-acceder-a-los-elementos-por-su-ndice-tanto-en-tuplas-como-en-listas">Se puede acceder a los elementos por su índice tanto en tuplas como en listas</h3><p>Como he mencionado anteriormente, tuplas y listas son una colección <strong>ordenada</strong> de elementos.</p><p>El orden es establecido e inmutable, siendo preservado durante toda la vida del programa.</p><p>El orden en que se especifican los elementos será siempre el mismo desde el momento en que son creados.</p><p>Cada valor en una tupla o una lista tiene un identificador único, su índice.</p><p>Cada elemento de una tupla/lista puede ser accedido haciendo referencia a su índice.</p><p>La indexación en Python (y en muchos otros lenguajes de programación y en Informática en general) comienza en <code>0</code>.</p><p>De modo que el primer elemento tiene índice <code>0</code>, el segundo tiene índice <code>1</code>, y así sucesivamente.</p><p>Para acceder a un elemento, escribe el nombre de la tupla/lista y a continuación el índice del elemento entre corchetes.</p><pre><code class="language-python">&gt;&gt;&gt;nombres = ("Jimmy","Timmy","John","Kate")

&gt;&gt;&gt;nombres[2]
'John'
</code></pre><p>O bien:</p><pre><code>&gt;&gt;&gt;lenguages_de_programacion = ["Python","JavaScript","Java","C"]

&gt;&gt;&gt;lenguages_de_programacion[0]
'Python'

&gt;&gt;&gt;lenguages_de_programacion[1]
'JavaScript'</code></pre><p>Bien, ya hemos visto en qué son similares, veamos ahora en qué difieren tuplas y listas.</p><h2 id="diferencias-entre-tuplas-y-listas-en-python">Diferencias entre tuplas y listas en Python</h2><h3 id="las-tuplas-son-inmutables-mientras-que-las-listas-son-mutables">Las Tuplas son inmutables, mientras que las Listas son mutables</h3><p>Las tuplas en Python son <strong>inmutables</strong>, lo que significa que una vez creada una tupla, sus elementos no pueden cambiar.</p><p>Las tuplas no pueden ser alteradas.</p><p>Si intentas cambiar el valor de uno de sus elementos, obtendrás un error:</p><pre><code class="language-python">&gt;&gt;&gt;nombres = ("Jimmy","Timmy","John","Kate")

&gt;&gt;&gt;nombres[2] = "Kelly"
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
TypeError: 'tuple' object does not support item assignment
</code></pre><p>No puedes añadir, reemplazar, reasignar o eliminar ningún elemento ya que las tuplas no pueden cambiar su configuración.</p><p>Esto implica que las tuplas tienen longitud fija. Su longitud nunca cambia a lo largo del ciclo de vida del programa.</p><h4 id="cuando-usar-tuplas">Cuando usar tuplas</h4><p>Las tuplas son una excelente opción si lo que quieres es que los datos de tu colección sean de solo lectura, que nunca cambien y se mantengan constantes. Tienen la capacidad de garantizar que los datos que contienen nunnca serán alterados.</p><p>Las tuplas pueden utilizarse como claves en un diccionario siempre que contengan tipos inmutables (cadenas, números u otras tuplas). Una lista, al ser mutable, no puede utilizarse para este fin.</p><h4 id="cuando-usar-listas">Cuando usar listas</h4><p>Por otro lado, las listas pueden ser fácilmente modificadas, ya que son <strong>mutables</strong>.</p><p>Se puede añadir elementos, eliminarlos, cambiarlos de posición o intercambiar unos por otros.</p><p>Las listas son útiles si lo que quieres es que tus datos sean flexibles, que puedan ser modificados cuando sea necesario.</p><p>Las listas soportan una variedad de métodos incorporados de Python que llevan a cabo ciertas operaciones sobre ellas, operaciones no soportadas por la tuplas.</p><p>Todo ello implica que la longitud, el tamaño de una lista pueda variar durante el ciclo de vida del programa.</p><p>Veamos ahora algunas operaciones sencillas que modifican una lista.</p><h2 id="como-actualizar-listas-en-python">Como actualizar listas en Python</h2><p>Ya que las listas son mutables, necesitarás conocer algunas de las formas básicas de actualizar los datos contenidos en una lista.</p><h3 id="como-actualizar-un-elemento-en-una-lista">Como actualizar un elemento en una lista</h3><p>Para actualizar un elemento en particular, hacemos referencia a su índice entre corchetes y asignamos el nuevo valor.</p><pre><code class="language-python"># sintaxis general
&gt;&gt;&gt;nombre_lista[indice] = nuevo_valor

&gt;&gt;&gt;lenguajes_de_programacion = ["Python","JavaScript","Java","C"]
&gt;&gt;&gt;print(lenguajes_de_programacion)
['Python', 'JavaScript', 'Java', 'C']

&gt;&gt;&gt;lenguajes_de_programacion[2] = "C++"
&gt;&gt;&gt;print(lenguajes_de_programacion)
['Python', 'JavaScript', 'C++', 'C']
</code></pre><h3 id="como-a-adir-elementos-a-una-lista">Como añadir elementos a una lista</h3><p>Hay varios métodos incorporados en Python para añadir elementos a una lista.</p><p>El método <code>.append()</code> añade un elemento nuevo<em> al final </em>de la lista.</p><pre><code class="language-python"># sintaxis general
&gt;&gt;&gt;nombre_lista.append(elemento)

&gt;&gt;&gt;lenguajes_de_programacion = ["Python","JavaScript","Java","C"]
&gt;&gt;&gt;print(lenguajes_de_programacion)
['Python', 'JavaScript', 'Java', 'C']

&gt;&gt;&gt;lenguajes_de_programacion.append("C++")

&gt;&gt;&gt;print(lenguajes_de_programacion)
['Python', 'JavaScript', 'Java', 'C', 'C++']
</code></pre><p>Para añadir el elemento en una posición determinada, usa el método &nbsp;<code>.insert()</code>.</p><p>Este método inserta el elemento en la posición dada. El resto de elementos de la lista que van después del elemento que se quiere insertar, son desplazados una posición hacia la derecha.</p><pre><code class="language-python"># sintaxis general
&gt;&gt;&gt;nombre_lista.insert(index,item)

&gt;&gt;&gt;nombres = ["Cody","Dillan","James","Nick"]
&gt;&gt;&gt;print(names)
['Cody', 'Dillan', 'James', 'Nick']


&gt;&gt;&gt;nombres.insert(0,"Stephanie")

&gt;&gt;&gt;print(nombres)
['Stephanie', 'Cody', 'Dillan', 'James', 'Nick']</code></pre><p>Si lo que se necesita es añadir más de un elemento, haremos uso del método <code>.extend()</code>.</p><p>Este método añade un iterable<em> al final </em>de la lista. Por ejemplo, se puede añadir una lista al final de una lista ya existente.</p><pre><code class="language-python"># sintaxis general
&gt;&gt;&gt;nombre_lista.extend(iterable)

&gt;&gt;&gt;lenguajes_de_programacion = ["Python","JavaScript"]
&gt;&gt;&gt;mas_lenguajes_de_programacion = ["Java","C"]

# añadir mas_lenguajes_de_programacion a lenguajes_de_programacion
&gt;&gt;&gt;lenguajes_de_programacion.extend(mas_lenguajes_de_programacion) 

&gt;&gt;&gt;print(programming_languages)
['Python', 'JavaScript', 'Java', 'C']
</code></pre><h3 id="como-eliminar-elementos-de-una-lista">Como eliminar elementos de una lista</h3><p>Hay dos métodos incorporados para eliminar elementos de una lista.</p><p>Uno de ellos es el método <code>.remove()</code>, que elimina la primera instancia del elemento que se le proporciona como argumento.</p><pre><code class="language-python"># sintaxis general
&gt;&gt;&gt;nombre_lista.remove(elemento)

&gt;&gt;&gt;lenguaje_de_programacion = ["Python", "JavaScript", "Java", "C"]
&gt;&gt;&gt;print(lenguaje_de_programacion)
['Python', 'JavaScript', 'Java', 'C']

&gt;&gt;&gt;lenguaje_de_programacion.remove("Java")
&gt;&gt;&gt;print(lenguaje_de_programacion)
['Python', 'JavaScript', 'C']

# elimina solo la primera ocurrencia
&gt;&gt;&gt;lenguaje_de_programacion = ["Python", "JavaScript", "Java", "C","Python"]
&gt;&gt;&gt;lenguaje_de_programacion.remove("Python")
&gt;&gt;&gt;print(lenguaje_de_programacion)
['JavaScript', 'Java', 'C', 'Python']
</code></pre><p>El otro es el método <code>.pop()</code>.</p><p>Si lo invocamos sin argumentos, eliminará el último elemento de la lista.</p><p>Se le puede pasar como argumento el índice del elemento específico que se quiera eliminar.</p><p>Este método devuelve el elemento eliminado, lo que puede ser útil en caso de que se quiera usar posteriormente, almacenándolo en una variable.</p><pre><code class="language-python">&gt;&gt;&gt;lenguaje_de_programacion = ["Python", "JavaScript", "Java", "C"]

&gt;&gt;&gt;lenguaje_de_programacion.pop()
'C'


&gt;&gt;&gt;print(lenguaje_de_programacion)
['Python', 'JavaScript', 'Java']

# guarda el valor retornado en una variable
&gt;&gt;&gt;lenguaje_de_programacion = ["Python", "JavaScript", "Java", "C"]

&gt;&gt;&gt;language_favorito = programming_languages.pop(0)
&gt;&gt;&gt;print(language_favorito)
Python</code></pre><h2 id="conclusi-n">Conclusión</h2><p>Aquí acabamos nuestra introducción sobre fundamentos de tuplas y listas y como son usadas normalmente.</p><p>Para recapitular, las <strong>similitudes</strong> entre tuplas y listas son:</p><ul><li>Son considerados objetos (instancias de una clase).</li><li>Son contenedores de colecciones de datos, pudiendo ser estos de cualquier tipo.</li><li>Son colecciones ordenadas, mantienendo siempre ese orden. Una vez que se ha definido el orden de los elementos, ya no cambiará. Esto puede parecer contradictorio en el caso de las listas. Una tupla mantiene su orden desde el mismo momento en que se crea, no pudiendo alterarlo el programador. En una lista podemos cambiar el orden, pero una vez establecido ese nuevo orden, se garantiza que se mantendrá hasta que decidamos volver a cambiarlo. Esta es una característica que no se garantiza, por ejemplo, en el caso de los diccionarios.</li><li>Tanto en tuplas como en listas puedes acceder a un elemento en particular mediante su índice.</li></ul><p>Las <strong>diferencias</strong> entre tuplas y listas son:</p><ul><li>Una tupla es <strong>inmutable</strong>. Úsalas cuando sepas con seguridad que tus datos no van a variar durante el ciclo de vida del programa o cuando quieras garantizar que se mantendrán constantes.</li><li>Una lista es <strong>mutable</strong>. Se puede añadir o eliminar elementos. Las listas crecen y decrecen durante la vida del programa. Úsalas cuando tus datos, por su propia naturaleza, sean susceptibles de variar.</li></ul><p>Si quieres aprender Python en profundidad, freeCodeCamp ofrece una <a href="https://www.freecodecamp.org/espanol/learn/scientific-computing-with-python/">certificación de Python</a> gratis.</p><p>El curso comienza con las bases más elementales y avanza hasta temas más complejos como estructuras de datos y bases de datos relacionales. Al final, hay cinco proyectos que solidificarán tus conocimientos.</p><p>¡Gracias por leer y feliz aprendizaje!</p><p>Dejo el enlace al <a href="https://docs.python.org/es/3/tutorial/">tutorial oficial de Python en español</a>.</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
