<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jorge Massih</title>
    <description>The latest articles on DEV Community by Jorge Massih (@plusiv).</description>
    <link>https://dev.to/plusiv</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F592592%2F78cee3f3-bfd0-4c9b-852f-358cb7e7ce38.png</url>
      <title>DEV Community: Jorge Massih</title>
      <link>https://dev.to/plusiv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/plusiv"/>
    <language>en</language>
    <item>
      <title>Hexagonal Architecture (Ports &amp; Adapters)</title>
      <dc:creator>Jorge Massih</dc:creator>
      <pubDate>Thu, 26 Feb 2026 15:41:10 +0000</pubDate>
      <link>https://dev.to/plusiv/hexagonal-architecture-ports-adapters-3adn</link>
      <guid>https://dev.to/plusiv/hexagonal-architecture-ports-adapters-3adn</guid>
      <description>&lt;p&gt;When I started in software engineering, I thought it was all about languages, frameworks and folders names, actually I remember when my biggest concern was about naming variables in a clear and understandable way — and don't get me wrong, those kind of stuff are really big important things to think, reflect and learn about, but if there's something that we must really care about when working on a project is picking a good Architecture, because that’s where the flexibility to make new changes easily lies. So in this article I'll try to teach you about how to stop your business logic from dating your database.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Do We Mean by Architecture?
&lt;/h2&gt;

&lt;p&gt;In the world of Software Engineering, architecture is a set of &lt;em&gt;high‑level&lt;/em&gt; decisions and constraints that shape how a system is built and how it evolves over time, and this involves thinking about how responsibilities are divided, or how components depend on each other, or even how easy it's to change something — and how much expensive it might be. &lt;/p&gt;

&lt;p&gt;A good architecture protects the parts of the system that change the least — &lt;em&gt;like business rules&lt;/em&gt; — from the parts that change the most — &lt;em&gt;like infrastructure and delivery mechanisms&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dirty Architecture?
&lt;/h3&gt;

&lt;p&gt;There's not such official term like a "dirty architecture" or "non-clean architecture", however there are signals for a bad architecture:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Business logic depends on frameworks&lt;/strong&gt;. It's not a common thing but just for a second think about what happens if you decide to decouple your framework from your project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Business logic depends on the database&lt;/strong&gt;. Have you ever thought about using a different database for your project? How much does it cost? And I'm not taking about switching the database driver for the ORM, I'm talking about replacing the whole storage layer. Don't get mad, but if switching from your SQL database to a file in the filesystem makes you to re-write the entire app, your architecture &lt;em&gt;s*cks&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Changing the transport is expensive&lt;/strong&gt;. You have a REST API and your team decides to switch to gRPC or GraphQL. Would that be an easy task, or would you need to start the project from scratch.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Clean Architecture
&lt;/h3&gt;

&lt;p&gt;What does exist is the term "Clean Architecture", introduced by Robert C. Martin (uncle Bob). You may know him for &lt;a href="https://www.amazon.com/stores/Robert-C.-Martin/author/B000APG87E" rel="noopener noreferrer"&gt;his books&lt;/a&gt;, or maybe for his &lt;a href="https://x.com/unclebobmartin/status/1925947718972645430" rel="noopener noreferrer"&gt;rants on X&lt;/a&gt;. He first wrote about Clean Architecture in a 2012 &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;blog post&lt;/a&gt;, and later in 2017 we got a &lt;a href="https://a.co/d/80LKWYJ" rel="noopener noreferrer"&gt;book&lt;/a&gt; about the same.&lt;/p&gt;

&lt;p&gt;The signals of a Clean Architecture are clear:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Business rules are independent of frameworks.&lt;/li&gt;
&lt;li&gt;Business rules are independent of databases.&lt;/li&gt;
&lt;li&gt;The system can evolve without rewriting core logic.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As for the rules, the Clean Architecture only has one rule: &lt;strong&gt;source code dependencies must point inward, toward the business rules&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw1v1m1fwcpvablo9evp0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw1v1m1fwcpvablo9evp0.png" alt="Clean Architecture explanation from Robert C. Martin's blog" width="772" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Original diagram by Robert C. Martin in his &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;blog&lt;/a&gt;, used for educational purposes.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You might be wondering, &lt;em&gt;"If it works, why do I need Clean Architecture?"&lt;/em&gt; I asked myself the same question before rewriting an entire service using a "clean" approach. The answer is simple: software rarely stays "done". A system can work perfectly today and still fail the business tomorrow—not because it crashes, but because it becomes too expensive to change.&lt;/p&gt;

&lt;p&gt;The key insight that I learned from Clean Architecture &lt;a href="https://a.co/d/80LKWYJ" rel="noopener noreferrer"&gt;book&lt;/a&gt; is to compare the extremes: &lt;em&gt;a program that works but is effectively unchangeable becomes useless the moment requirements evolve, while a program that is easy to change can be made to work and kept working as the business learns&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;In practice, systems don’t become literally unchangeable, they become economically unchangeable when the cost of change exceeds the value. Clean Architecture is a practical way to stay on the “easy to change” side of that trade‑off by keeping dependencies pointed inward (toward business rules) and treating frameworks, databases, and delivery mechanisms as replaceable details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hexagonal Architecture
&lt;/h2&gt;

&lt;p&gt;I could say this is one of the most famous Clean Architectures nowadays, the Hexagonal Architecture or better known as Ports and Adapters, introduced by Alistair Cockburn on &lt;a href="https://alistair.cockburn.us/hexagonal-architecture" rel="noopener noreferrer"&gt;his blog&lt;/a&gt; in 2005.&lt;/p&gt;

&lt;p&gt;It's known as Ports and Adapter because "&lt;strong&gt;Ports&lt;/strong&gt;" are the abstract interfaces that define the protocols and interactions your application exposes or requires according to the business rules, and "&lt;strong&gt;Adapters&lt;/strong&gt;" are the concrete implementations of those ports for specific technologies like HTTP handlers, databases, queues. And the reason because it's also called "Hexagonal Architecture" &lt;strong&gt;is not&lt;/strong&gt; because it's required to have six things; it’s because the hexagon shape shows how multiple interfaces connect with the outside world.&lt;/p&gt;

&lt;p&gt;This makes input mechanisms (HTTP, CLI, gRPC) and output mechanisms (Postgres, Redis, APIs) interchangeable without changing the core logic. Think about your project as a Lego system. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr9x6g8m510aqq8w0g2ak.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr9x6g8m510aqq8w0g2ak.png" alt="Hexagonal Architecture in an image" width="800" height="717"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The goal of the image above is to highlight that the boundary of the application is what matters: inside are the business rules and use cases, and outside are all the ways the application connects with the world. &lt;/p&gt;

&lt;p&gt;You may have also noticed in the image above the distinction between a "&lt;em&gt;Driving side&lt;/em&gt;" and a "&lt;em&gt;Driven side&lt;/em&gt;". This concept comes from Cockburn's original Ports &amp;amp; Adapters (Hexagonal) model. The driving (primary) side consists of actors and adapters that initiate actions into the application core — such as user interfaces, HTTP/gRPC requests, CLI commands, or test scripts. The driven (secondary) side consists of actors and adapters that the application itself drives in order to fulfill its work — such as databases, external services, or other systems. The distinction is based on who triggers the interaction: driving adapters call into the core through its ports, while driven adapters implement the ports that the core calls to interact with external technology. This separation helps ensure that the business logic remains isolated from and independent of specific technologies or protocols.&lt;/p&gt;

&lt;p&gt;In conclusion, if your architecture allows you to refactor code and change transport mechanisms, databases, or queues as easily as swapping your car’s wheels, then you’ve reached the Valhalla of software engineering — a place where change is expected, not feared.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>systemdesign</category>
      <category>cleancode</category>
      <category>cleanarchitecture</category>
    </item>
    <item>
      <title>Estructuras de Datos para Network Engineers 101: Hash Tables (Parte II)</title>
      <dc:creator>Jorge Massih</dc:creator>
      <pubDate>Fri, 21 May 2021 13:20:12 +0000</pubDate>
      <link>https://dev.to/plusiv/estructuras-de-datos-para-network-engineers-101-hash-tables-parte-ii-1a10</link>
      <guid>https://dev.to/plusiv/estructuras-de-datos-para-network-engineers-101-hash-tables-parte-ii-1a10</guid>
      <description>&lt;h2&gt;
  
  
  Introducción
&lt;/h2&gt;

&lt;p&gt;Según lo que vimos en la &lt;a href="https://dev.to/jorgmassih/estructuras-de-datos-para-network-engineers-101-hash-tables-parte-i-5go1"&gt;primera parte&lt;/a&gt;, deberíamos de ser hábiles para entender una Tabla de Hash, en la cual se basará la aplicación que desarrollaremos en este post.&lt;/p&gt;

&lt;p&gt;Recuerda que queremos crear una aplicación que nos automatice la asociación de alguna interfaz de nuestro switch con una vlan especifica. A su vez, la vlan estará relacionada con una MAC-Address.&lt;/p&gt;

&lt;p&gt;Normalmente en una oficina se tiene el siguiente escenario:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbmjaubyvjhvvu9pqt6pe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbmjaubyvjhvvu9pqt6pe.png" alt="Alt Text" width="511" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Los dispositivos que utilizamos en el día a día se conectan a un Switch de Acceso, en dicho equipos asociamos Vlans especificas con interfaces a las que están conectadas los dispositivos.&lt;/p&gt;

&lt;p&gt;La idea de esta aplicación, es que el proceso de asignación a una Vlan cada vez que conectamos un dispositivo a una interfaz, se haga de manera automática. De igual forma cuando dicho dispositivo sea desconectado de la interfaz correspondiente.&lt;/p&gt;
&lt;h2&gt;
  
  
  Alcance
&lt;/h2&gt;

&lt;p&gt;Hay que tomar en cuenta que esta aplicación será desarrollada de la manera más básica posible, ya que sólo es una demostración de aplicación de una Estructura de Dato, por lo que hay ciertos features que no podrán ser cubiertos. Dicho esto, nuestro alcance será el siguiente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cada interfaz sólo podrá tener una sola MAC-Address.&lt;/li&gt;
&lt;li&gt;La aplicación asumirá que la IP del dispositivo ya fue dada, por lo que no contempla el uso de DHCP, NTP, ni otro tipo de servicio.&lt;/li&gt;
&lt;li&gt;Sólo se abarcarán equipos Cisco y con el &lt;em&gt;cisco ios&lt;/em&gt; como sistema operativo.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Módulos a utilizar
&lt;/h2&gt;

&lt;p&gt;Esta aplicación se soportará de dos módulos esenciales:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://pypi.org/project/netmiko/" rel="noopener noreferrer"&gt;Netmiko&lt;/a&gt;: Simplifica las conexiones a equipos de Red. Estaremos utilizando este módulo para conectarnos por SSH a los equipos para automatizar tareas y extraer información de sus configuraciones.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://ttp.readthedocs.io/en/latest/Overview.html" rel="noopener noreferrer"&gt;Text Template Parser (TTP)&lt;/a&gt;: Este es un módulo que permite parsear de manera rápida data semi-estructurada mediante plantillas o templates. Estaremos utilizando este módulo para sacar la información útil de la data extraída de los equipos. Por ejemplo, si corremos el comando &lt;code&gt;show ip interface brief&lt;/code&gt;, este nos devolverá una tabla, para poder extraer los valores útiles de esa tabla (IPs asignadas, estado de la interfaz, entre otras cosas) podemos auxiliarnos de &lt;a href="https://es.wikipedia.org/wiki/Expresi%C3%B3n_regular" rel="noopener noreferrer"&gt;Regular Expressions&lt;/a&gt; o RegEx; Este módulo facilita la extracción de valores ya que crea el RegEx a partir de una plantilla en donde se le muestra como pueden venir los datos.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nota&lt;/strong&gt;: Este no es un tutorial acerca de estos módulos, por lo que si querrás saber más sobre como usar Netmiko, te refiero a su &lt;a href="https://pynet.twb-tech.com/blog/automation/netmiko.html" rel="noopener noreferrer"&gt;documentación para empezar a usaro&lt;/a&gt;, de igual manera con TTP, debes ir a la &lt;a href="https://ttp.readthedocs.io/en/latest/Quick%20start.html" rel="noopener noreferrer"&gt;documentación&lt;/a&gt; para aprender a usarlo a fondo.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Funcionamiento
&lt;/h2&gt;

&lt;p&gt;Cuando se conecta un dispositivo a nuestro switch, este guarda su MAC-Address en una tabla; nuestra aplicación se mantendrá atenta a la tabla de MACs, y cuando aparezca una nueva, se busca en la Base de Datos, si está ahí, automáticamente se configura dicha interfaz con la Vlan que aparece en la Base de Datos para dicha MAC, también, se utiliza la funcionalidad de &lt;a href="https://packetlife.net/blog/2010/may/3/port-security/" rel="noopener noreferrer"&gt;Port Security&lt;/a&gt; para asegurarse que que no se conecten más dispositivos que los autorizados a dicho puerto.&lt;/p&gt;

&lt;p&gt;Cuando un dispositivo se desconecte del switch, la interfaz se apagará, la aplicación estará atenta a dichas interfaces para restaurarlas a su estado por defecto y esta pueda ser utilizada por otro dispositivo que se conecte.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nota&lt;/strong&gt;: Por defecto las interfaces contienen la vlan 1, asumiremos que esta será nuestra vlan de Black-hole para dispositivos no identificados.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ya sabes como es esto, tu no me entiendes, y yo te dejo una imagen que te explica mejor 😜😆&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw34pcp8f5qr44e7j39hb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw34pcp8f5qr44e7j39hb.png" alt="Alt Text" width="800" height="746"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Base de Datos
&lt;/h2&gt;

&lt;p&gt;En este caso, para simplicidad, utilizaremos un archivo de configuración como Base de Datos, en dicho archivo pondremos los datos de las MAC Address y en que Vlans las queremos.&lt;/p&gt;

&lt;p&gt;A continuación un ejemplo de la estructura que diseñé para que la aplicación pueda leer dicho archivo sin problemas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nota&lt;/strong&gt;: los Keys o Values que estén entre caracteres &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt; están hábiles para ser cambiados.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hosts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"&amp;lt;hostname&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"deviceType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cisco_ios"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;device-username&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;device-password&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"secret"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;enable-secret&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"macs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"&amp;lt;mac1&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;vlan-id&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"&amp;lt;mac2&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;vlan-id&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"&amp;lt;mac3&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;vlan-id&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"&amp;lt;mac4&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;vlan-id&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Más adelante veremos como quedó el que utilizaré para la demostración.&lt;/p&gt;
&lt;h2&gt;
  
  
  Archivos de comandos de configuración
&lt;/h2&gt;

&lt;p&gt;Los comandos de configuraciones de los equipos pudieran estar en el código, sin embargo, ponerlos en archivos aparte y extraer los comandos de ahí a la hora de utilizarlos es una solución más elegante. A continuación los 2 archivos de configuración que utilizaré.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;create_vlan.conf&lt;/code&gt;: Estos son los comandos para asociar una interfaz a una Vlan cuando encontremos una MAC nueva en la tabla y que esté en la Base de Datos.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vlan {vlan}
interface {interface}
switchport mode access
switchport access vlan {vlan}
switchport port-security
switchport port-security maximum 1
switchport port-security violation protect
switchport port-security mac-address {mac}
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;restore_interface.conf&lt;/code&gt;: Estos son los comandos para volver una interfaz a su estado por defecto cuando se desconecte un dispositivo y la aplicación lo detecte.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface {interface}
no switchport port-security
no switchport port-security violation protect
no switchport port-security mac-address
switchport access vlan 1
no switchport nonegotiate
no switchport mode access
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Templates
&lt;/h2&gt;

&lt;p&gt;Acordamos en que utilizaríamos un modulo para extraer la información de los switches, este módulo requiere del uso de plantillas que modelen como vendrá la información. Este no es un tutorial del uso de Text Template Parser (puedo hacer uno en el futuro si lo piden), para eso te dejé la documentación más arriba. Si no quieres leer, puedes quedar con la idea abstracta de lo que hace el módulo, después de todo, lo importante es entender como incorporamos la estructura a nuestro código.&lt;/p&gt;

&lt;p&gt;A continuación los templates que utilicé:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;interfaces.xml&lt;/code&gt;: Plantilla de la estructura de la tabla dada por el comando &lt;code&gt;show ip interface brief&lt;/code&gt;, el cual utilizaremos para saber si las interfaces están prendidas o apagadas.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;group&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;'{{ interface }}'&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;'table'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
{{ interface }}     {{ ignore }}      {{ ignore }} {{ ignore }}  {{ status }}                  {{ ignore }}
&lt;span class="nt"&gt;&amp;lt;/group&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;mactable.xml&lt;/code&gt;: Plantilla de la estructura de la tabla dada por el comando &lt;code&gt;show mac address-table&lt;/code&gt;, el cual utilizaremos para saber si hay una MAC Address en la tabla sin inspeccionar.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;group&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"{{ mac }}"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"table"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   {{ vlan | DIGIT }}    {{ mac }}    {{ type }}     {{ port }}
   {{ vlan | DIGIT }}    {{ mac }}    {{ type }}      {{ port }}
  {{ vlan | DIGIT }}    {{ mac }}    {{ type }}      {{ port }}
  {{ vlan | DIGIT }}    {{ mac }}    {{ type }}     {{ port }}
&lt;span class="nt"&gt;&amp;lt;/group&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Let's go to code
&lt;/h2&gt;

&lt;p&gt;Ahora vamos a cocinar 😎.&lt;/p&gt;

&lt;p&gt;Creamos una clase llama MBVlan (adivina el nombre) que será la que representará todas las funcionalidades de nuestra aplicación. En el método &lt;code&gt;__init__&lt;/code&gt; instanciamos nuestra clase. En ese momento creamos un atributo que guarda el estado inicial del estado de las interfaces, es decir: si están &lt;em&gt;up&lt;/em&gt; o &lt;em&gt;down&lt;/em&gt;. La idea es que cada vez que se detecte un cambio en el estado de las interfaces, este atributo se actualice. En cuanto al método que se usa &lt;code&gt;get_interfaces&lt;/code&gt;, hablaremos de eso más adelante.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;netmiko&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ConnectHandler&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;ttp&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ttp&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MBVlan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;([(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;interfaces&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_interfaces&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt;
                             &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hosts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;

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

&lt;/div&gt;


&lt;p&gt;La propiedad &lt;code&gt;_config&lt;/code&gt; nos devuelve el archivo de configuración en forma de un diccionario de Python.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;config.json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Hay dos métodos importantes para la interacción con los equipos, el primero es &lt;code&gt;_get_device_config&lt;/code&gt;, este nos devuelve la configuración del archivo de configuracion para ese dispositivo o switch. El otro método es &lt;code&gt;_get_device_conn&lt;/code&gt;, el cual gestiona una conexión mediante Netmiko con los dispositivos de red, en este caso son los switches. Fijémonos que se auxilia con el método mencionado anteriormente para obtener los parámetros de conexión estipulados en el archivo de configuración.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_get_device_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hosts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;device_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_get_device_conn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;device_conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_device_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConnectHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;device_conf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;deviceType&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;device_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                              &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;device_conf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                              &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;device_conf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                              &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;device_conf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;secret&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Tenemos dos métodos estáticos (que he colocado dentro de la clase para no crear otro archivo) que nos servirán para cargar contenido en archivos. El primero, &lt;code&gt;open_conf&lt;/code&gt; nos abre los archivos de comandos configuración más arriba. El segundo, &lt;code&gt;_load_template&lt;/code&gt; nos abre los archivos &lt;code&gt;xml&lt;/code&gt; que contienen las plantillas a parsear para extraer la información útil entre toda la que nos muestran los equipos.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;open_conf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;commands/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.conf&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;conf_template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;conf_template&lt;/span&gt;

    &lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;./templates/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.xml&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;El método que se encarga de cargar las plantilla es de suma importancia porque nos ahorra espacio en nuestro archivo de código, este es usado en los métodos que te voy a mostrar a continuación, &lt;code&gt;get_interfaces&lt;/code&gt; y &lt;code&gt;get_tables&lt;/code&gt;, los cuales utilizan los módulos que mencionamos al principio para extraer información de los equipos (en este caso los switches) y luego extraer la información que es útil, ya que es mucho texto que necesitamos procesar para entender el estado de la red. Hay algo importante que mencionar sobre TTP, y es que devuelve la data en un diccionario, recuerda que esta es la propia Tabla de Hash de Python, esto nos facilitará acceder a cualquier dato de una manera bastante rápida, tal como lo describimos en la &lt;a href="https://dev.to/jorgmassih/estructuras-de-datos-para-network-engineers-101-hash-tables-parte-i-5go1"&gt;primera parte&lt;/a&gt;. Notarás que se hace uso del &lt;em&gt;statement with&lt;/em&gt; en esta porción de código, si no sabes para que se usa te recomiendo leer &lt;a href="https://www.educative.io/edpresso/the-with-statement-in-python" rel="noopener noreferrer"&gt;esto&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_interfaces&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Crea una nueva connección con netmiko
&lt;/span&gt;        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_device_conn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;interfaces&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;interfaces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;show ip interface brief&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Usa la plantilla que describe el comando 'show ip interface brief'
&lt;/span&gt;            &lt;span class="c1"&gt;# para parsear la data que devuelve a la salida.
&lt;/span&gt;            &lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ttp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="c1"&gt;# Aísla la salida dada por el switch y elimina del diccionario
&lt;/span&gt;            &lt;span class="c1"&gt;# el key "Interface", el cual es innecesario porque es el head
&lt;/span&gt;            &lt;span class="c1"&gt;# de la tabla obtenida.
&lt;/span&gt;            &lt;span class="n"&gt;interfaces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Interface&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;interfaces&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;table_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Crea una nueva connección con netmiko
&lt;/span&gt;        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_device_conn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;table_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Usa la plantilla que describe la salida del comando para
&lt;/span&gt;            &lt;span class="c1"&gt;# la tabla de mac address y devuelve la data usable
&lt;/span&gt;            &lt;span class="n"&gt;mac_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;show mac address-table&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ttp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mac_table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;# Aisla la salida
&lt;/span&gt;            &lt;span class="n"&gt;mac_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mac_table&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Debes recordar, que acorde con el diagrama de flujo que viste al principio, habían dos operaciones sumamente importantes, una de ellas asignaba la vlan correspondiente a la interfaz del nuevo dispositivo conectado al switch, esto lo hacemos mediante el método &lt;code&gt;_update_interfaces&lt;/code&gt;, el cual recibe en un diccionario la información de los hosts registrados en el archivo de Base de Datos y que están actualmente conectados algún equipo de la red, se itera sobre el diccionario y se  este diccionario también contiene informaciones como que tenemos que actualizar mediante la asignación de una Vlan y la activación del feature &lt;em&gt;Port Security&lt;/em&gt;. La función de dicho método es sencilla, este busca todas las interfaces en el diccionario y luego carga el archivo de comandos en el dispositivo al que corresponde dicha interfaz mediante el uso de Netmiko. &lt;/p&gt;

&lt;p&gt;La otra operación importante revisaba las interfaces que recién se habían apagado por desconexión del host, de ser el caso, dicha interfaz volvía a su estado por defecto, es decir, vlan por defecto y funcionalidades de &lt;em&gt;Port Security&lt;/em&gt; deshabilitadas. Todo esto lo hacemos mediante el método &lt;code&gt;_restore_interfaces&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nota&lt;/strong&gt;: Para lograr saber que interfaz se apagó recientemente, la aplicación monitorea la tabla de interfaces cada cierto tiempo y guarda el estado de esta, cuando se detecta un cambio, es porque una interfaz pasó de tener un estado "up" a "down"&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_update_interface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Crea una nueva connección con netmiko
&lt;/span&gt;        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_device_conn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;conf_template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open_conf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;create_vlan&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Itera sobre el diccionario de los hosts en el archivo 
&lt;/span&gt;            &lt;span class="c1"&gt;# de Base de Datos
&lt;/span&gt;            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;legal_host&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Agrega las variables de cada host a la platilla de comandos 
&lt;/span&gt;                &lt;span class="n"&gt;commands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conf_template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vlan&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;legal_host&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;vlan&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;legal_host&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
                                                &lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;legal_host&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;
                           &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_config_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_restore_interfaces&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Crea una nueva connección con netmiko
&lt;/span&gt;        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_device_conn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;conf_template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open_conf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;restore_interface&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Itera sobre las interfaces a restaurar valores por defecto
&lt;/span&gt;            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Agrega las variables de cada host a la platilla de comandos  
&lt;/span&gt;                &lt;span class="n"&gt;commands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conf_template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_config_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ya casi para terminar la explicación de todo el código, existe un método que es como la cereza del pastel, se llama &lt;code&gt;diff&lt;/code&gt;, este se encarga de notar los cambios de estados en los dispositivos, es decir, cambios en la tabla de MAC-Address y en el estado de las Interfaces. Este método es el que llama a los métodos &lt;code&gt;_update_interface&lt;/code&gt; y &lt;code&gt;_restore_interfaces&lt;/code&gt; cuando detecta cambios.&lt;/p&gt;

&lt;p&gt;En pocas palabras podemos decir que este método es el Core de todo el proyecto, de hecho, el diagrama de flujo del principio del post es una descripción a nivel general de este método.&lt;/p&gt;

&lt;p&gt;Debido a que la información se representa en una Tabla de Hash, no es tan costoso a nivel de procesamiento hacer operaciones con esta, ya que sólo se necesita acceder al &lt;em&gt;Key&lt;/em&gt; correspondiente para tener el &lt;em&gt;Value&lt;/em&gt; deseado en un tiempo constante (

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(1)O(1)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
). Te pongo un ejemplo para la detección del cambio en la tabla de MACs de un switch, esta vez utilizaré una imagen:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypq8i5stbw1erw72uos8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypq8i5stbw1erw72uos8.png" alt="Alt Text" width="598" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con respecto a la detección de cambio de estado de las interfaces, debemos recordar que cuando la clase &lt;code&gt;MBVlan&lt;/code&gt; es instanciada, se crea el atributo &lt;code&gt;devices&lt;/code&gt; con el estado de todas las interfaces de todos los equipos (espero que te acuerdes de eso), y cada vez que se llama al método &lt;code&gt;diff&lt;/code&gt;, dicho atributo es actualizado. La siguiente imagen muestra la actuación del método &lt;code&gt;diff&lt;/code&gt; en los cambios de estado de las interfaces.&lt;/p&gt;

&lt;p&gt;Para hacer la diferenciación entre las interfaces que siguen encendidas y las que se apagaron, se utiliza la Estructura de Datos basada en &lt;a href="https://edu.gcfglobal.org/es/los-conjuntos/clases-de-conjuntos/1/" rel="noopener noreferrer"&gt;Teoría de Conjuntos&lt;/a&gt; llamada &lt;a href="https://recursospython.com/guias-y-manuales/conjuntos-sets/" rel="noopener noreferrer"&gt;Set&lt;/a&gt;, recuerda que dijimos en el post de &lt;a href="https://dev.to/jorgmassih/estructura-de-datos-para-network-engineers-101-introduccion-4j0k"&gt;introducción&lt;/a&gt; que íbamos a hablar de esta estructura, pues llegó el momento. Sucede que, es lo mimo que una Tabla de Hash, pero el &lt;em&gt;Value&lt;/em&gt; siempre será &lt;code&gt;None&lt;/code&gt;, y, ya que en una Tabla de Hash el Key nunca está en 2 posiciones al mismo tiempo, es imposible que se repita, por lo que podemos tener una estructura donde se almacenen elementos (que en este caso son los &lt;em&gt;Keys&lt;/em&gt; de la Tabla de Hash) y que no se repitan. Ingenioso, ¿no?&lt;/p&gt;

&lt;p&gt;Esta estructura permite hacer operaciones parecidas a las que describe la Teoría de Conjuntos; para nuestra implementación utilizamos la operación de &lt;a href="https://www.sangakoo.com/es/temas/diferencia-de-conjuntos" rel="noopener noreferrer"&gt;Diferencia de Conjuntos&lt;/a&gt; para ver los cambios entre los estados de interfaces en caché mediante el atributo &lt;code&gt;devices&lt;/code&gt; y los estados actuales obtenidos mediante el método &lt;code&gt;get_interfaces&lt;/code&gt;. Por el momento, los cambios de estado de las interfaces de &lt;em&gt;down&lt;/em&gt; a &lt;em&gt;up&lt;/em&gt; no nos interesan (aunque pudieran eficientizar la aplicación, pero añadirían más complejidad), por lo que los filtraremos para ignorarlos en el resultado final. ¿Confundido? Es que he explicado mucho, pero aquí un una imagen que te aclarará el proceso:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zfh3gq0mwic2yo3wm0x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0zfh3gq0mwic2yo3wm0x.png" alt="Alt Text" width="654" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nota&lt;/strong&gt;: La complejidad de la operación &lt;code&gt;Difference&lt;/code&gt; de B y A es de 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(len(B))O(len(B)) &lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;l&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
. Se está utilizando la estructura Built-in de Python, puedes ver los tiempos de complejidad que emplea &lt;a href="https://wiki.python.org/moin/TimeComplexity#set" rel="noopener noreferrer"&gt;aquí&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A continuación te dejo con la porción de código que describe la intención del método &lt;code&gt;diff&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;new_macs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;switch_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mactable&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;file_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_get_device_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;macs&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;cached_int_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;interfaces&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;current_int_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_interfaces&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Obtiene la diferencia entre el estado actual de las int
&lt;/span&gt;        &lt;span class="c1"&gt;# y el que se tiene almacenado
&lt;/span&gt;        &lt;span class="n"&gt;int_off&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;current_int_status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;down&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cached_int_status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;down&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Si existe interfaces apagadas recientemente, las restaura a su estado inicial
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;int_off&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_restore_interfaces&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;int_off&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Actualiza el estado de las interfaces
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;interfaces&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_int_status&lt;/span&gt;

        &lt;span class="c1"&gt;# Busca nuevos hosts conectados al switch que esten en el archivo de BD
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;mac&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;switch_table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;file_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;switch_table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;vlan&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;file_table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;vlan&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="n"&gt;new_macs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;file_table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;switch_table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mac&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]}})&lt;/span&gt;

        &lt;span class="c1"&gt;# Si hay nuevos hosts, entonces actualiza sus interfaces
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;new_macs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_update_interfaces&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_macs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nota&lt;/strong&gt;: La actualización del atributo &lt;code&gt;devices&lt;/code&gt; pudiera optimizarse y hacerse sólo cuando se detecte un cambio, sin embargo, al igual que otras cosas en la implementación, se ha dejado como está para poder simplificarla y que sea más entendible&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Por último, si lo anterior fue la cereza en el helado, esto es la mermelada; se ha creado un método para correr la aplicación, de modo que a la hora de instanciar la clase, el siguiente paso es llamar a este método, se trata de &lt;code&gt;run&lt;/code&gt;, el cual no hace más que iterar sobre todos dispositivos disponibles en nuestro archivo de base de datos &lt;code&gt;config.json&lt;/code&gt; y llamar el método &lt;code&gt;diff&lt;/code&gt; con cada dispositivo. Esto se hace a una frecuencia de muestreo deseada, yo puse 5 segundos en el ejemplo para fines demostrativos, pero, mientras más alta es la frecuencia de muestreo (tiempo bajo), será más fácil para nuestra aplicación detectar los cambio en nuestros equipos de red o switches.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;running...&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;devices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Por lo que tendríamos:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MBVlan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Demostración y Conclusión
&lt;/h2&gt;
&lt;h4&gt;
  
  
  Escenario
&lt;/h4&gt;

&lt;p&gt;La topología siguiente describe el escenario que utilizaremos para la prueba, donde tendremos dos switches de acceso, los cuales se conectan por una red de administración con el servidor que está corriendo el script. La configuración de estos switches solo contempla la de las interfaces de administración y el protocolo de SSH para que el módulo de Netmiko tenga acceso a ellos.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcw2s5mu56iolz5trr0d4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcw2s5mu56iolz5trr0d4.PNG" alt="Alt Text" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cualquiera de los hosts que están en el diagrama deben de poder conectarse a cualquiera de los dos switches y ser asignados automáticamente a la Vlan correspondiente.&lt;/p&gt;
&lt;h4&gt;
  
  
  Archivo de configuración
&lt;/h4&gt;

&lt;p&gt;Este es el archivo que utilicé como Base de Datos:&lt;br&gt;
&lt;code&gt;config.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hosts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"192.168.56.154"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"deviceType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cisco_ios"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"secret"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"macs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"0050.7966.6800"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"0050.7966.6801"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"20"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"0050.7966.6802"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"0050.7966.6803"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"30"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"0050.7966.6804"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"40"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"0050.7966.6805"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"40"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"0050.7966.6806"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"30"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"192.168.56.155"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"deviceType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cisco_ios"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"secret"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"macs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"0050.7966.6800"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"0050.7966.6801"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"20"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"0050.7966.6802"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"0050.7966.6803"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"30"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"0050.7966.6804"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"40"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"0050.7966.6805"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"40"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"0050.7966.6806"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"vlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"30"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Look at the demo
&lt;/h4&gt;

&lt;p&gt;Aquí un pequeño video del resultado, quiero hacer dos aclaraciones al respecto; la primera es que hice algunos cortes al video para acortar su duración, la segunda aclaración es que, una vez los hosts tienen una IP asignada de forma manual (debido a que en el escenario presentado no hay servidor DHCP), estos necesitan enviar tráfico hacia el switch para que este pueda aprender sus direcciones MACs, por lo que en el video se ve cuando se da ping hacia una IP que no existe en la red para forzar el aprendizaje de la MAC Address por parte del Switch, en un ambiente de producción de la vida real esto no es necesario.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/552423841" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;
&lt;h4&gt;
  
  
  Conclusión
&lt;/h4&gt;

&lt;p&gt;La Tabla de Hash fue clave para el desarrollo de esta aplicación, vemos como en algunas partes de la misma utilizamos algoritmos que corren en una complejidad lineal de 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(n)O(n)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, por lo que utilizar una Lista o un Array pudo haber elevado la complejidad hasta 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(n3)O(n^3)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, sin embargo, las operaciones de esta estructura entregan mejor complejidad, lo que da la oportunidad a nuestra aplicación de tener mejor rendimiento.&lt;/p&gt;

&lt;p&gt;Por otra parte, tocamos la automatización, la cual es una herramienta muy poderosa, y más cuando se combina con las estructuras de datos adecuadas, y por eso es muy importante conocerlas todas ellas. Ahora te toca a ti ¿Qué piensas automatizar en tu red?¿Qué estructura utilizarías?&lt;/p&gt;

&lt;p&gt;Aquí te dejo el proyecto completo:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@Jorgmassih/mac-based-vlan-ver001?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/jorgmassih" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.buymeacoffee.com%2Fbutton-api%2F%3Ftext%3DBuy%2520me%2520a%2520coffee%2520here%26emoji%3D%25E2%258C%25A8%25EF%25B8%258F%26slug%3Djorgmassih%26button_colour%3D5F7FFF%26font_colour%3Dffffff%26font_family%3DLato%26outline_colour%3D000000%26coffee_colour%3DFFDD00" width="280.0" height="50"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>hash</category>
      <category>python</category>
      <category>netmiko</category>
      <category>networkautomation</category>
    </item>
    <item>
      <title>Estructuras de Datos para Network Engineers 101: Hash Tables (Parte I)</title>
      <dc:creator>Jorge Massih</dc:creator>
      <pubDate>Mon, 03 May 2021 13:20:47 +0000</pubDate>
      <link>https://dev.to/plusiv/estructuras-de-datos-para-network-engineers-101-hash-tables-parte-i-5go1</link>
      <guid>https://dev.to/plusiv/estructuras-de-datos-para-network-engineers-101-hash-tables-parte-i-5go1</guid>
      <description>&lt;h2&gt;
  
  
  Introducción
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Aqui es donde se separan los niños de los hombres."&lt;/em&gt;&lt;br&gt;
— Yo en mi mente cuando empecé a aprender Tablas de Hash.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A muchas personas se les dificulta aprender Tablas de Hash, recuerdo que fue la Estructura de Datos que menos me gustó cuando la vi en la universidad, realmente es una estructura relativamente fácil de aprender, y aquí trataré de explicártela lo mejor posible. &lt;/p&gt;

&lt;p&gt;Esta estructura tambien tiene la particularidad de que es &lt;strong&gt;MÁGICA&lt;/strong&gt;, sí, mágica, es una de las Estructuras de Datos más eficientes y rápidas, esto es porque su tiempo de ejecución es constante en el caso promedio. En el primer post mencionamos algo relacionado con complejidad de un algoritmo y su tiempo de ejecución, las Tablas de Hash tienen una complejidad tremendamente buena, abajo te lo detallo.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Algoritmo&lt;/th&gt;
&lt;th&gt;Caso Promedio&lt;/th&gt;
&lt;th&gt;Peor Caso&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Inserción&lt;/td&gt;
&lt;td&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(1)O(1)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(n)O(n)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Busqueda&lt;/td&gt;
&lt;td&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(1)O(1)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(n)O(n)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eliminación&lt;/td&gt;
&lt;td&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(1)O(1)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(n)O(n)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;La motivación de este post será un poco más práctica, se trata de una aplicación que estoy desarrollando sobre &lt;a href="https://kb.netgear.com/21586/What-is-a-MAC-based-VLAN-and-how-does-it-work-with-my-managed-switch" rel="noopener noreferrer"&gt;Mac Based Vlan&lt;/a&gt; para equipos Cisco que no poseen diche feature. Se estará implementando una Tabla de Hash y se usará el módulo de &lt;a href="https://pynet.twb-tech.com/blog/automation/netmiko.html" rel="noopener noreferrer"&gt;Netmiko&lt;/a&gt;, el cual se utiliza para Network Automation. Pero, debido a lo extenso que podría salir este post, lo dividiré en dos partes, en esta te explico todo el fundamento y luego en el otro te explico como desarrollé la aplicación.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es una Hash Table?
&lt;/h2&gt;

&lt;p&gt;La Tabla de Hash es una Estructura de Datos de manera "asociativa", esto quiere decir, que tiene que asociar "algo" con "algo" para llevar a cabo sus operaciones. &lt;/p&gt;

&lt;p&gt;Antes de explicar como funciona, volvamos al pasado, al &lt;a href="https://dev.to/jorgmassih/estructuras-de-datos-para-network-engineers-101-las-linked-list-50n9"&gt;primer post&lt;/a&gt;: Habíamos dicho que un array o lista, almacena los elementos en bloques de memoria contiguos (uno al lado del otro), eso facilita muchas cosas, como el acceso a algún índice de esa estructura de manera instantánea. Esto nos dice que, si tuviéramos el índice de un elemento en un array o lista, pudiéramos acceder de inmediato a dicho elemento, en un tiempo constante, es decir, no hay que recorrer toda la estructura para llegar a ese elemento.&lt;/p&gt;

&lt;p&gt;En la estructura de la Tabla de Hash tenemos 3 componentes importantes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Los elementos a insertar&lt;/li&gt;
&lt;li&gt;Una función de Hash&lt;/li&gt;
&lt;li&gt;La Tabla de Hash&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;El primer componente, es decir, los elementos a insertar, se identifican con un &lt;strong&gt;Key&lt;/strong&gt; único, esto quiere decir que, la manera de nosotros insertar o extraer un valor de la estructura es mediante dicho &lt;em&gt;Key&lt;/em&gt;, dicho Key es elegido por nosotros. Podemos ver el &lt;em&gt;Key&lt;/em&gt; como un apodo que le ponemos a nuestro valor para poder identificarlo dentro de la estructura, por ejemplo: en mi familia habemos muchos con nombre de Jorge, mi papá se llama Jorge, mi hermano mayor se llama Jorge, uno de mis hermanos más pequeños se llama Jorge, uno de mis primos se llama Jorge, y yo tal vez le ponga Jorge a un hijo mío para no perder la cultura 😂😂, cuando hacemos reuniones familiares y estamos todos los Jorges, usan nuestros segundos nombres (el cual sirve de &lt;em&gt;Key&lt;/em&gt;) para referirse a nosotros.&lt;/p&gt;

&lt;p&gt;Luego que entendemos el concepto, debemos buscar la manera de asociar el &lt;em&gt;Key&lt;/em&gt; a la estructura, esto nos lleva al segundo componente importante, la &lt;a href="https://es.wikipedia.org/wiki/Funci%C3%B3n_hash" rel="noopener noreferrer"&gt;función de Hash&lt;/a&gt;, esta recibe el &lt;em&gt;Key&lt;/em&gt; como entrada y retorna un número. Es como una cafetera, le hechas el café y el agua y luego esta te devuelve el resultado. Es importante destacar que dicho número debe ser generado por funciones que corran en tiempo constante, las funciones de Hash eficientes utilizan operaciones matemáticas para lograrlo. &lt;/p&gt;

&lt;p&gt;Luego, lo que procede es almacenar los valores en la tabla, ¿Cómo se crea la tabla? Es una lista o arreglo. ¿En que índice de la lista o arreglo almaceno los elementos? En el índice del número obtenido por la Función de Hash. ¿Aún sigues sin entender 😅? Tranquilo, a continuación te presento la hiper-mega-apoteósica imagen explicativa:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxfn5022carx4yatwy5c5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxfn5022carx4yatwy5c5.png" alt="Alt Text" width="542" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una forma "fácil" en la que aprendí a ver las Tablas de Hash fue la siguiente: imagina que vas a un hospital a consultarte con tu médico, cuando llegas, alguien en la recepción te atiende, tu le dices a que médico quieres ir, y dependiendo del médico que sea te dicen el número del consultorio al que debes ir. Lo mismo pasa con las Tablas de Hash, de acuerdo al &lt;em&gt;Key&lt;/em&gt; de algún &lt;em&gt;Value&lt;/em&gt;, la Función de Hash retornará un número correspondiente a dicha posición en la tabla (recuera que es una lista o arreglo) donde debe ir el &lt;em&gt;Value&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A continuación te dejo un ejemplo: supongamos que queremos guardar las edades (nuestro &lt;em&gt;Value&lt;/em&gt;) de personas, y las asociaremos a sus nombres (nuestro &lt;em&gt;Key&lt;/em&gt;). &lt;/p&gt;

&lt;p&gt;Para que esta explicación sea lo más simple posible, utilizaremos una Función de Hash sencilla; tomaremos cada letra del nombre de la persona (el &lt;em&gt;Key&lt;/em&gt;), las convertiremos en su &lt;a href="https://elcodigoascii.com.ar" rel="noopener noreferrer"&gt;valor ASCII&lt;/a&gt; y las sumaremos.&lt;/p&gt;

&lt;p&gt;Los algoritmos de Hash suelen retornar números grandes, esto puede provocar que necesitemos índices grandes dentro de la tabla, lo que se traduce a mucha ocupación en memoria. Algo que se suele hacer es ajustar dicho índice al tamaño de nuestra tabla, es decir, si nuestra tabla será de tamaño de 100 índices, entonces dividimos el número entre 100 y tomamos el residuo (o resto) porque este nunca será mayor al divisor, esto nos garantiza que el valor del hash nunca quedará fuera de la tabla cuando utilicemos un número fijo de valores. En nuestro ejemplo utilizaremos una tabla de tamaño 5, por lo que tendremos que obtener el 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;mod  5\mod 5&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mspace allowbreak"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathrm"&gt;mod&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 de las sumas resultantes de los valores de los caracteres, entonces, ese resultado será nuestro índice dentro de la tabla. A continuación, una imagen que vale más que mil palabras que te pueda escribir 😉.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2w4dcl7cqx9s2tsosnr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2w4dcl7cqx9s2tsosnr.png" alt="Alt Text" width="492" height="242"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Colisiones
&lt;/h4&gt;

&lt;p&gt;Ya estamos claros en que el índice en donde se alojarán los datos es dados por una función de Hash, pero, ¿Qué pasa si dos &lt;em&gt;Keys&lt;/em&gt; producen el mismo número de índice cuando pasan por la Función de Hash? Bueno, en ese caso explota la Tabla de Hash, tienes que activar de inmediato la alarma anti incendios y a parte de eso, correr lo más lejos posible en el menor tiempo posible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft2rdioc7znv3n2gw2mzz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft2rdioc7znv3n2gw2mzz.gif" alt="Alt text of image" width="385" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nah!😂😂, cuando eso pasa ocurre lo que se llama una "Colisión", por lo regular, las colisiones ocurren en los malos algoritmos de Funciones de Hash, de hecho, en teoría estas están siempre supuestas a pasar, no obstante un buen diseño de dicha función reduce las probabilidades de que estas ocurran. Si te interesa el diseño de Funciones de Hash te dejo este &lt;a href="https://link.springer.com/content/pdf/10.1007/3-540-58108-1_10.pdf" rel="noopener noreferrer"&gt;&lt;em&gt;Paper&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3g0qmj89h6vqqvrygvd0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3g0qmj89h6vqqvrygvd0.png" alt="Alt Text" width="492" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tal como se muestra en la imagen anterior, existe una colisión en el ejemplo anterior cuando intentamos insertar a 'Felisa' en la Tabla de Hash, esto porque su índice correspondiente coincide con el índice para 'Isaac'.&lt;/p&gt;
&lt;h4&gt;
  
  
  Lidiando con Colisiones
&lt;/h4&gt;

&lt;p&gt;Existen varias maneras, porque después de todo, hay que almacenar más de un dato en la misma posición de la tabla, una muy popular es &lt;a href="https://www.educative.io/edpresso/what-is-chaining-in-hash-tables" rel="noopener noreferrer"&gt;The Chainning Technique&lt;/a&gt;, esta consiste en tener una Estructura de Datos como una Linked List en cada índice de la Tabla de Hash. Debido a las colisiones es que se dijo al principio que en el peor caso las operaciones en la Tabla de Hash tomarían una complejidad de tiempo de 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(n)O(n)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, el peor de los casos se da cuando todas entradas a la Tabla de Hash producen colisiones entre ellas y por consiguiente, se almacenarían en el mismo lugar y tendriamos que recorrer toda la Linked List de tamaño 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;nn&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 para llegar al elemento que queremos. Te lo explico mejor con una ilustración.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F06yrmo8xyd3hnpshc338.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F06yrmo8xyd3hnpshc338.png" alt="Alt Text" width="662" height="299"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Creando nuestra propia Tabla de Hash
&lt;/h2&gt;

&lt;p&gt;Antes de empezar, quisiera decir que el lenguaje que hemos estado utilizando a lo largo de esta serie contiene esta Estructura de Datos de manera &lt;em&gt;Built-in&lt;/em&gt;, no obstante, estaremos realizando nuestra propia estructura para demostrar los conceptos que hemos explicado anteriormente. Es importante mencionar que se utilizará &lt;em&gt;Chainning Technique&lt;/em&gt; para manejar las colisiones, para emplear dicho mecanismo haremos uso de nuestra clase Linked List creada en el &lt;a href="https://dev.to/jorgmassih/estructuras-de-datos-para-network-engineers-101-las-linked-list-50n9"&gt;primer post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Primero debemos definir los nodos a utilizar en nuestra Tabla de Hash, ya que estos serán utilizados por nuestras Linked Lists, podríamos utilizar la clase &lt;code&gt;Nodo&lt;/code&gt; del principio, pero ahora tenemos un atributo adicional que representa al &lt;em&gt;Key&lt;/em&gt;, entonces, haciendo uso del segundo y tercer pilar de la POO, la encapsulación y la herencia; crearemos una clase que herede de la clase &lt;code&gt;Nodo&lt;/code&gt; para añadir el atributo de &lt;code&gt;key&lt;/code&gt;. Si quieres saber más acerca de los 4 pilares de la POO, &lt;a href="https://info.keylimeinteractive.com/the-four-pillars-of-object-oriented-programming" rel="noopener noreferrer"&gt;te recomiendo esto&lt;/a&gt;, de todos modos pienso hacer una serie sobre POO.&lt;br&gt;
&lt;/p&gt;

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

        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nota importante&lt;/strong&gt;: Recordemos que una Key es un atributo inmutable, y cambiarlo podría implicar moverlo en la Tabla de Hash. Dicha operación no es permitida en esta estructura, entonces, haremos uso de la propiedad &lt;code&gt;key&lt;/code&gt; y no le crearemos un setter para que no se pueda modificar.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ahora vamos a crear nuestra clase &lt;code&gt;HashTable&lt;/code&gt;, recordemos que dicha tabla tiene que tener un tamaño específico, también debe tener una Función de Hash asociada para colocar los elementos de acuerdo a su &lt;code&gt;key&lt;/code&gt;, por lo cual, como parámetro para instanciar la clase vamos a requerir un número &lt;code&gt;size&lt;/code&gt; y una Función de Hash &lt;code&gt;hash_func&lt;/code&gt;. Adicional, tenemos el atributo &lt;code&gt;hash_function&lt;/code&gt; que nos define la Función de Hash requerida, y tambien el atributo de la tabla &lt;code&gt;table&lt;/code&gt;, el cual no es más que una lista de Linked Lists vacías del tamaño del atributo &lt;code&gt;size&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HashTable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hash_func&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hash_function&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hash_func&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;LinkedList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_test_hash_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hash function must return a lower number than Hash Table size: {}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nota&lt;/strong&gt;: La Función de Hash estará como parametro en la clase debido a que la queremos de manera implicita, esto es para poder modificarla de acuerdo a la aplicación del Hash.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Como se pudo observar, se introdujo una función llamada &lt;code&gt;_test_hash_value&lt;/code&gt;, la cual velará porque la Funcion de Hash no retorne un valor que pueda estár fuera del índice de la tabla, de ocurrir, se activará una excepcion.&lt;/p&gt;

&lt;p&gt;Luego, procedemos con los métodos más importantes: los de insertar y buscar elementos en la Tabla de Hash, para ambos vamos a utilizar los &lt;em&gt;Magic Methods&lt;/em&gt; &lt;code&gt;__setitem__&lt;/code&gt; y &lt;code&gt;__getitem__&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Para insertar en la tabla, se obtiene el valor calculado por la Función de Hash y luego se ubica la Linked List de esa posición en la tabla, si la tabla está vacía es porque no hay ningún otro elemento y no ha ocurrido una colisión, sólo tendríamos que asignar el nodo al &lt;em&gt;head&lt;/em&gt; de esa Linked List. Cuando ocurre una colisión, se debe insertar el nodo al final de la Linked List. En el caso de la actualización de algún &lt;em&gt;value&lt;/em&gt;, se buscará en la Linked List por por dicho &lt;em&gt;Key&lt;/em&gt; y &lt;em&gt;Value&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Para buscar en la tabla, hacemos un procedimiento similar, primero sometemos el &lt;em&gt;key&lt;/em&gt; a la Función de Hash, luego, accedemos a la Linked List en esa posición y verificamos si el &lt;em&gt;Key&lt;/em&gt; se encuentra en la misma.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__setitem__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HashNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# obtiene el indice calculado por la función de hash
&lt;/span&gt;        &lt;span class="n"&gt;hash_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# verifica si el valor del índice está en la tabla
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_test_hash_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# obtiene la linked list del índice obtenido
&lt;/span&gt;        &lt;span class="n"&gt;table_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hash_value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# asigna el nodo a la posición si no hay algun otro
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;table_value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;table_value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;

        &lt;span class="c1"&gt;# lidia con las colisiones y la actualización de values
&lt;/span&gt;        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;hash_node&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;table_value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# si el key ya está en la tabla, lo actualiza
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;hash_node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;hash_node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
                    &lt;span class="k"&gt;break&lt;/span&gt;
                &lt;span class="c1"&gt;# si ocurre una colisión, añade el nodo al final
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;hash_node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;hash_node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;
                    &lt;span class="k"&gt;break&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__getitem__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# obtiene el indice calculado por la función de hash
&lt;/span&gt;        &lt;span class="n"&gt;hash_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# verifica si el valor del índice está en la tabla
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_test_hash_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hash_value&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;

        &lt;span class="c1"&gt;# si no hay nodo en la cabeza de la LL, entonces está vacia
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

        &lt;span class="c1"&gt;# busca un nodo en la Linked List
&lt;/span&gt;        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
            &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;

        &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;

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

&lt;/div&gt;


&lt;p&gt;Por último, tenemos la función para remover elementos, la cual es básicamente la misma que la función que la de inserción, sólo que una vez encontrado el nodo, lo desvincula de la Linked List. Esto se hace a través de una método llamado &lt;code&gt;unlink&lt;/code&gt; añadido a nuestra clase &lt;code&gt;Linked List&lt;/code&gt;, esta clase elimina un nodo especifico de una Linked List.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# obtiene el indice calculado por la función de hash
&lt;/span&gt;        &lt;span class="n"&gt;hash_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# verifica si el valor del índice está en la tabla
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_test_hash_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# verifica si el nodo existe para desvincularlo
&lt;/span&gt;        &lt;span class="c1"&gt;# de una linked list en específico
&lt;/span&gt;        &lt;span class="n"&gt;item_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;item_value&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

        &lt;span class="n"&gt;table_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hash_value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;table_value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unlink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HashNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item_value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

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

&lt;p&gt;Aunque estamos en la parte conclusiva, esto no quiere decir que cerraremos este tema aquí, ya sabes los fundamentos, el siguiente post será totalmente práctico. Verás una aplicación utilizando el módulo de &lt;a href="https://pypi.org/project/netmiko/" rel="noopener noreferrer"&gt;Netmiko&lt;/a&gt; y otros más que facilitan tareas de automatización.&lt;/p&gt;

&lt;p&gt;Por otra parte, creamos una clase que maneja las Tablas de Hash de manera correcta, tal vez no sea la más óptima pero sirve para practicar los conceptos. Mi profesor de Estructura de Datos decía que la mejor forma para comprobar los conocimientos es hacer una implementación de estos, aunque también decía que en teoría, la teoría y la práctica son lo mismo; sin embargo, en la práctica no ocurre así... ¿Paradójico verdad?&lt;/p&gt;

&lt;p&gt;A continuación, haremos una comparación de desempeño entre la clase que hemos hecho con la que Python ya trae de manera &lt;em&gt;Built-in&lt;/em&gt;, a partir de los resultados decidiremos cual vamos a utilizar para desarrollar la aplicación del siguiente post. Abajo te dejo el Replit del código utilizado junto con la demostración.&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@Jorgmassih/Hashtabletutorial?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/jorgmassih" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.buymeacoffee.com%2Fbutton-api%2F%3Ftext%3DBuy%2520me%2520a%2520coffee%2520here%26emoji%3D%25E2%258C%25A8%25EF%25B8%258F%26slug%3Djorgmassih%26button_colour%3D5F7FFF%26font_colour%3Dffffff%26font_family%3DLato%26outline_colour%3D000000%26coffee_colour%3DFFDD00" width="280.0" height="50"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>hash</category>
      <category>python</category>
      <category>netmiko</category>
      <category>networkautomation</category>
    </item>
    <item>
      <title>Estructuras de Datos para Network Engineers 101: Queues &amp; Stacks</title>
      <dc:creator>Jorge Massih</dc:creator>
      <pubDate>Mon, 26 Apr 2021 13:59:27 +0000</pubDate>
      <link>https://dev.to/plusiv/estructuras-de-datos-para-network-engineers-101-queues-stacks-4c8n</link>
      <guid>https://dev.to/plusiv/estructuras-de-datos-para-network-engineers-101-queues-stacks-4c8n</guid>
      <description>&lt;p&gt;Antes de empezar a leer, es recomendable tener manejo del lenguaje de programación &lt;a href="https://es.wikipedia.org/wiki/Python" rel="noopener noreferrer"&gt;Python 3&lt;/a&gt;, también conocimientos en &lt;a href="https://j2logo.com/python/tutorial/programacion-orientada-a-objetos/" rel="noopener noreferrer"&gt;Programación Orientada a Objetos (POO)&lt;/a&gt;. No es estrictamente necesario, pero importante, tener por lo menos nociones del concepto &lt;a href="https://recursospython.com/guias-y-manuales/clases-metodos-magicos-y-propiedades/" rel="noopener noreferrer"&gt;Magic Methods (ó Dundder Methods)&lt;/a&gt; de Python.&lt;/p&gt;

&lt;p&gt;También, te recomiendo que visites el post anterior (si no lo has hecho) acerca de las &lt;a href="https://dev.to/jorgmassih/estructuras-de-datos-para-network-engineers-101-las-linked-list-50n9"&gt;Linked List&lt;/a&gt;, ya que reutilizaremos algunos conceptos de estos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducción
&lt;/h2&gt;

&lt;p&gt;Tecnologías como White Box Switches (WBS) se están levantando hoy en día con el auge del Software Defined Networking (SDN), en pocas palabras: Los WBS, se refieren a equipos de red que son "&lt;em&gt;anti-vendors&lt;/em&gt;" y como tal, sólo vienen con el &lt;em&gt;hardware&lt;/em&gt; necesario para lidiar con tráfico de red y opcionalmente un Sistema Operativo (comúnmente una distribución de Linux), después de ahí las demás funcionalidades de esos equipos quedan a tu responsabilidad. &lt;a href="https://www.sdxcentral.com/data-center/bare-metal/white-box/definitions/what-is-white-box-networking/" rel="noopener noreferrer"&gt;Aquí puedes saber algo más&lt;/a&gt; si tanto te gustó el tema.&lt;/p&gt;

&lt;p&gt;Para animarte a seguir leyendo, te voy a plantear una situación, y es la que estaremos tratando de solucionar a lo largo de este post. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Supón que llegó a tus manos un WBS, y tu trabajo es instalar en el sistema operativo aplicaciones que brinden las funcionalidades de red que tu compañía necesita, sin embargo, hay un problema: el equipo nuevo puede quedarse ahogado al intentar acomodar el tráfico recién llegado, esto ocurre si la velocidad de llegada del tráfico es mayor que la velocidad a la que este le da salida. En tal situación, el tráfico que va llegando se ignora, es decir, ocurre el famoso &lt;a href="https://en.wikipedia.org/wiki/Packet_loss" rel="noopener noreferrer"&gt;&lt;em&gt;Packet Loss&lt;/em&gt;&lt;/a&gt;, a esta situación en las interfaces de red algunos fabricantes le dicen &lt;a href="https://www.cisco.com/c/en/us/support/docs/dial-access/asynchronous-connections/15286-serial-overruns.html" rel="noopener noreferrer"&gt;Overruns&lt;/a&gt;. Como parte de los mecanismos de asignación de recursos, los equipos de red deben implementar algún tipo de técnica para gobernar la forma en que el tráfico se almacena en el &lt;a href="https://es.wikipedia.org/wiki/B%C3%BAfer_de_datos" rel="noopener noreferrer"&gt;buffer&lt;/a&gt; del equipo&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es una Queue?
&lt;/h2&gt;

&lt;p&gt;Imagina que estas bebiendo mucha agua, e inclinas la cabeza hacia atrás junto con el vaso, si tragas muy lento con relación a la velocidad a la que baja el agua del vaso, llegará un momento donde esta se botará de tu boca y harás un tremendo reguero 😓. Como ya se mencionó antes, algo similar pasa con los equipos de redes. Las Queues vienen a resolver este problema.&lt;/p&gt;

&lt;p&gt;Una Queue o Cola (ya sabes del post anterior que aquí usamos anglicismos 😜) es una Estructura de Datos lineal que almacena los datos de forma ordenada, en donde los primeros en entrar, son los primeros en salir, este mecanismo es llamado &lt;a href="https://es.wikipedia.org/wiki/First_in,_first_out" rel="noopener noreferrer"&gt;FIFO (First In, First Out)&lt;/a&gt;. Son algo similar a la fila que haces en el banco, o cuando esperas en una llamada a un &lt;em&gt;Call Center&lt;/em&gt; porque todos los operadores están ocupados. Te dejo una imagen para que veas a lo que me refiero.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpxbs074evl9nwutd8pry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpxbs074evl9nwutd8pry.png" alt="Alt Text" width="696" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como te habrás podido imaginar, en la imagen anterior, el objeto que sigue para extraer es &lt;code&gt;obj1&lt;/code&gt;, luego &lt;code&gt;obj2&lt;/code&gt;, y si quisieras &lt;code&gt;obj4&lt;/code&gt; tendrías que sacar &lt;code&gt;obj3&lt;/code&gt; primero.&lt;/p&gt;

&lt;p&gt;Para insertar un elemento hacemos una operación llamada &lt;strong&gt;Enqueue&lt;/strong&gt;, que no es nada más que insertar el elemento al final de la Queue (&lt;strong&gt;Rear&lt;/strong&gt;). Existe una otra operación importante llamada &lt;strong&gt;Dequeue&lt;/strong&gt;, la cual se refiere a extraer el elemento en turno, es decir, el primero (&lt;strong&gt;Front&lt;/strong&gt;). Cabe destacar que cuando se hace un Dequeue, se debe desvincular de la estructura dicho elemento y se debe de poner como primero (&lt;strong&gt;Front&lt;/strong&gt;) al que le sigue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementando nuestra propia Queue
&lt;/h3&gt;

&lt;p&gt;Debido a que ya habíamos implementado una Linked List en el post anterior, vamos a reutilizarla y hacer la implementación sobre dicha Linked List. Sí, esto es válido, podemos ver nuestra Queue como una Linked List que sólo puede retirar el nodo &lt;em&gt;head&lt;/em&gt; y se puede insertar despues del último elemento. Entonces, tenemos que el &lt;strong&gt;Front&lt;/strong&gt; será nuestro &lt;em&gt;head&lt;/em&gt; y el &lt;strong&gt;Rear&lt;/strong&gt; será el último elemento de la Linked List.&lt;/p&gt;

&lt;p&gt;Para la implementación utilizaremos el concepto de &lt;a href="https://ellibrodepython.com/herencia-en-python" rel="noopener noreferrer"&gt;herencia&lt;/a&gt; del campo de POO, por lo que nuestra clase &lt;em&gt;Queue&lt;/em&gt; heredará de la clase &lt;em&gt;Linked List&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

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

        &lt;span class="c1"&gt;# Si se pasó una lista, crea la Linked List a partir de esta
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list_to_linked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Podemos utilizar el atributo &lt;code&gt;head&lt;/code&gt; como nuestro Front, y ya que no podemos renombrar en la clase hija los atributos de la clase padre, podemos utilizar los &lt;a href="https://pythones.net/propiedades-en-python-oop#Propiedades_de_atributos_de_clase_en_Python_Getter_Setter_y_Deleter" rel="noopener noreferrer"&gt;métodos Setter y Getter nativos de Python&lt;/a&gt; para hacer un pseudo cambio de nombre.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;front&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;

    &lt;span class="nd"&gt;@front.setter&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;front&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nota&lt;/strong&gt;: cambiar el nombre sería lo correcto porque agrega legibilidad y contexto al código, es decir, hace que se vea más "limpio"&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;El siguiente paso es crear los métodos para &lt;em&gt;Enqueing&lt;/em&gt; y &lt;em&gt;Dequeing&lt;/em&gt;. Para &lt;em&gt;Enqueing&lt;/em&gt; la estrategia será hacer uso del método &lt;code&gt;append()&lt;/code&gt; que se hereda de nuestra clase &lt;code&gt;Linked List&lt;/code&gt;, dicho método sólo recorre la Linked List y e inserta el elemento al final (Rear). Para &lt;em&gt;Dequeing&lt;/em&gt; la idea es vincular el &lt;em&gt;Front&lt;/em&gt; con el nodo siguiente al primero. ¿Confundido😵? Te dejo una imagen que te sacará de apuros:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Froveqrzzjlfkrjw5zdai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Froveqrzzjlfkrjw5zdai.png" alt="Alt Text" width="681" height="246"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;enqueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;equeueing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Llama el método heredado 'append', el cual itera sobre
&lt;/span&gt;        &lt;span class="c1"&gt;# la lista y agrega el nuevo Nodo después del Nodo último
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;equeueing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dequeue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Desvincula el Front de su Nodo y lo apunta al siguiente
&lt;/span&gt;        &lt;span class="n"&gt;dequeued&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;front&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;front&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;front&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
        &lt;span class="n"&gt;dequeued&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dequeued&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  ¿Qué es un Stack?
&lt;/h2&gt;

&lt;p&gt;Imagina que estás montando cajas en un camión, y las pones una al lado de la otra, llegará un momento donde no habrá más espacio para las cajas, por lo que recurrirás a organizarlas de una manera más eficiente. Ponerlas una arriba de otra es la opción más común, y la que todos preferiríamos, básicamente de eso se trata el Stack o Pila. Otro ejemplo es la pila de platos que se arma antes y/o después de lavarlos, cuando vas a tomar un plato, sacas el que está en la cima para no tumbar los otros, de igual manera, cuando vas a insertar un plato, lo colocas arriba. En esta estructura se colocan los datos de manera que el último en llegar es el primero en salir, dicho mecanismo se conoce como &lt;a href="https://es.wikipedia.org/wiki/Last_in,_first_out" rel="noopener noreferrer"&gt;LIFO (Last In, First Out)&lt;/a&gt;. Principalmente los equipos de red utilizan esta estructura para consultar registros del tráfico, por lo regular, los que se desean ver son los últimos, por eso es más convenientes tenerlos de primero.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh8gjjmlfvvifir3lhw93.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh8gjjmlfvvifir3lhw93.png" alt="Alt Text" width="335" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como se puede observar, al último elemento (el cual es el primero en salir) se le llama &lt;strong&gt;Top&lt;/strong&gt;. Las operaciones básicas con esta estructura son &lt;strong&gt;Push&lt;/strong&gt; y &lt;strong&gt;Pop&lt;/strong&gt;, la primera inserta un elemento de último  y la segunda retira ese elemento que está de último (como cuando te toca coger 4 cartas jugando &lt;a href="https://es.wikipedia.org/wiki/Uno_(juego)" rel="noopener noreferrer"&gt;UNO&lt;/a&gt;😂). &lt;/p&gt;
&lt;h3&gt;
  
  
  Implementando nuestro propio Stack
&lt;/h3&gt;

&lt;p&gt;De igual forma, utilizaremos nuestra clase &lt;code&gt;Linked List&lt;/code&gt; para implementar nuestro Stack. Podemos ver nuestro Stack como una Linked List que sólo puede retirar el nodo &lt;em&gt;Top&lt;/em&gt; (que realmente es nuestro &lt;em&gt;head&lt;/em&gt;) y se puede insertar al principio (el &lt;em&gt;Top&lt;/em&gt;).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nota&lt;/strong&gt;: de igual forma que con la Clase Queue, utilizaremos los métodos Setter y Getter nativos de Python para renombrar el head como Top&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LinkedList&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Si se pasó una lista, crea la Linked List a partir de esta
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# La lista está invertida para mantener el concepto de Stack
&lt;/span&gt;            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list_to_linked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lst&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;top&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;

    &lt;span class="nd"&gt;@top.setter&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;top&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Los métodos &lt;em&gt;Pop&lt;/em&gt; y &lt;em&gt;Push&lt;/em&gt; serán similares, de hecho, son inversos. Para el método Pop, utilizaremos la misma técnica que para el proceso de Dequeing (sí, es lo mismo realmente 😆), por lo que puedes volver a consultar la imagen que lo explica si tienes dudas. En el caso del método Push, lo que haremos será utilizar un método ya incorporado en la clase &lt;code&gt;Linked List&lt;/code&gt; que se llama &lt;code&gt;insert_first()&lt;/code&gt;, este método desvincula el &lt;em&gt;Top&lt;/em&gt; (que realmente es el head) del primer nodo y luego lo apunta al nuevo nodo a insertar (recuerda que te dije que era el proceso inverso a Pop 😉). ¿Confundido de nuevo😵? &lt;em&gt;don't worry my friend&lt;/em&gt;, aquí tienes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsmp7b125cy7vinw3bkb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsmp7b125cy7vinw3bkb.png" alt="Alt Text" width="681" height="246"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Llama al método heredado 'insert_first', el cual agrega
&lt;/span&gt;        &lt;span class="c1"&gt;# un nodo en la primera posición de la Linked List 
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert_first&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Desvincula el Top del nodo a extraer y lo vincula al siguiente
&lt;/span&gt;        &lt;span class="n"&gt;popped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
        &lt;span class="c1"&gt;# Apunta el nodo extraido a None
&lt;/span&gt;        &lt;span class="n"&gt;popped&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;popped&lt;/span&gt;

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

&lt;/div&gt;

&lt;h2&gt;
  
  
  Resolviendo los problemas con lo aprendido
&lt;/h2&gt;

&lt;p&gt;Para resolver el problema planteado en la introducción, vamos a implementar una Queue como Estructura de Datos para mantener los datos en memoria estructurados en dicho estilo, de modo que se vayan acumulando y salgan en el orden de llegada, es decir, el trafico más viejo primero (FIFO).&lt;/p&gt;

&lt;p&gt;Para hacer la aplicación un poco más didáctica y que podamos ver el funcionamiento de la Queue, la centraremos en una simulación de la llegada y salida del tráfico en un tiempo especifico generados aleatoriamente, esto provocará que los paquetes se vayan acumulando en la Queue. Para esto crearemos dos funciones que corran como dos procesos "más o menos paralelos", una para simular la recepción del tráfico y otra para la simulación de la transmisión. Para esto haremos uso de &lt;a href="https://www.genbeta.com/desarrollo/multiprocesamiento-en-python-threads-a-fondo-introduccion" rel="noopener noreferrer"&gt;Threads&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;También, para hacer el ejercicio más visual, representaremos la Queue en una tabla, donde se especificará el orden de salida. El Id del tráfico (un número generado aleatoriamente para fines de demostración), el tiempo de llegada y las interfaces de entrada y salida. &lt;/p&gt;

&lt;p&gt;Para la representación de la tabla utilizaremos un módulo externo llamado &lt;a href="https://pypi.org/project/prettytable/" rel="noopener noreferrer"&gt;Prettytable&lt;/a&gt;, el cual puede instalarse fácilmente vía &lt;a href="https://pypi.org/project/pip/" rel="noopener noreferrer"&gt;pip&lt;/a&gt; como: &lt;code&gt;pip install -U prettytable&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Crearemos una clase llamada &lt;code&gt;TrafficQueue&lt;/code&gt; que heredará de la clase creada anteriormente &lt;code&gt;Queue&lt;/code&gt;. Esta clase será muy sencilla y su diseño es muy fácil, ya que sólo agrega 2 componentes. El primer componente es un atributo llamado &lt;code&gt;frame_table&lt;/code&gt;, que servirá para instanciar el objeto del módulo que nos ayudará a crear la tabla. El segundo componente es un &lt;a href="https://javadesdecero.es/poo/overriding-o-anulacion-metodos/#:~:text=En%20cualquier%20lenguaje%20de%20programaci%C3%B3n,sus%20superclases%20o%20clases%20principales." rel="noopener noreferrer"&gt;&lt;em&gt;Overriding&lt;/em&gt;&lt;/a&gt; al magic method de &lt;code&gt;__repr__&lt;/code&gt;, esto es para que a la hora de imprimir la Queue, imprimamos la tabla como una representación.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;prettytable&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PrettyTable&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;Utils.DataStructures.ds&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TrafficQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Atributo utilizado para imprimir la tabla
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frame_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PrettyTable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frame_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Index&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Time&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;In Interface&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Out Interface&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list_to_linked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__repr__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Agrega todos los nodos de la Queue a la tabla
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frame_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear_rows&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;front&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                &lt;span class="n"&gt;frame_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frame_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_row&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_int&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frame_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TrafficQueue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_time&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Espera el tiempo indicado para simular la llegada del tráfico
&lt;/span&gt;    &lt;span class="c1"&gt;# en interfaces de entrada y salida aleatorias
&lt;/span&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;frame_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
        &lt;span class="n"&gt;frame_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ctime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;input_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Agrega la información del trafico generado a la Queue
&lt;/span&gt;        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enqueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_int&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;        

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_time&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Espera el tiempo indicado para simular la salida del tráfico
&lt;/span&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dequeue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;app&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Lista de los números de interfaces a simular
&lt;/span&gt;    &lt;span class="n"&gt;interfaces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Tiempo de entrada/salida del tráfico
&lt;/span&gt;    &lt;span class="c1"&gt;# El tiempo de entrada debe ser menor
&lt;/span&gt;    &lt;span class="n"&gt;input_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Crea los threads
&lt;/span&gt;    &lt;span class="n"&gt;rx_thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_time&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;tx_thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_time&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;

    &lt;span class="n"&gt;rx_thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;tx_thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;refresh_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;

    &lt;span class="c1"&gt;# Hará una actualización de la taba en el tiempo estipulado
&lt;/span&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;refresh_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;clear&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;posix&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cls&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Network Equipment Interfaces Queue&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

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

&lt;p&gt;Realizamos una aplicación que concentra el uso de Queues y explica la importancia de estas en el mundo de las redes computacionales. Cabe destacar que lo importante de la parte de Queues fue la explicación de la estructura mediante la implementación de una aplicación que maneja el reenvío del tráfico en nuestros equipos de red. Normalmente estos equipos ya traen implementado un sistema de Queues para resolver la problemática planteada, sin embargo, existe la posibilidad de que se necesite crear una variante propia de la implementación, para hacer modelos de QoS y demás, de ser así, si prestaste atención, entonces lo tienes cubierto.&lt;/p&gt;

&lt;p&gt;Te dejo el repositorio de replit con todo el código desarrollado y la aplicación final. Te recomiendo que la abras en la web de replit directamente y pongas el apartado de la consola más grande para que se puede apreciar bien la tabla.&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@Jorgmassih/Queues-y-Stacks-Tutorial?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/jorgmassih" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.buymeacoffee.com%2Fbutton-api%2F%3Ftext%3DBuy%2520me%2520a%2520coffee%2520here%26emoji%3D%25E2%258C%25A8%25EF%25B8%258F%26slug%3Djorgmassih%26button_colour%3D5F7FFF%26font_colour%3Dffffff%26font_family%3DLato%26outline_colour%3D000000%26coffee_colour%3DFFDD00" width="280.0" height="50"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>networking</category>
      <category>queuestack</category>
      <category>python</category>
      <category>datastructure</category>
    </item>
    <item>
      <title>Estructuras de Datos para Network Engineers 101: Las Linked Lists</title>
      <dc:creator>Jorge Massih</dc:creator>
      <pubDate>Mon, 19 Apr 2021 13:20:19 +0000</pubDate>
      <link>https://dev.to/plusiv/estructuras-de-datos-para-network-engineers-101-las-linked-list-50n9</link>
      <guid>https://dev.to/plusiv/estructuras-de-datos-para-network-engineers-101-las-linked-list-50n9</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Es recomendable tener manejo del lenguaje de programación &lt;a href="https://es.wikipedia.org/wiki/Python" rel="noopener noreferrer"&gt;Python 3&lt;/a&gt;, también conocimientos en &lt;a href="https://j2logo.com/python/tutorial/programacion-orientada-a-objetos/" rel="noopener noreferrer"&gt;Programación Orientada a Objetos (POO)&lt;/a&gt;. No es estrictamente necesario, pero si importante, tener por lo menos nociones del concepto &lt;a href="https://recursospython.com/guias-y-manuales/clases-metodos-magicos-y-propiedades/" rel="noopener noreferrer"&gt;Magic Methods (ó Dundder Methods)&lt;/a&gt; de Python.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Introducción
&lt;/h1&gt;

&lt;p&gt;Es muy probable que cundo se hable de organizar datos de manera secuencial tu primera opción sea intentar utilizar un Array (conocido por algunos como Arreglo) o Lista, y bueno, no te culpo, también era el mío antes de conocer por completo el maravilloso mundo de las Estructuras de Datos. No está mal usar dichas estructuras, pero existen otras alternativas para situaciones específicas que harán que tus implementaciones sean más fáciles, seguras y eficientes.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es una Linked List?
&lt;/h2&gt;

&lt;p&gt;Linked List o Lista Enlazada (&lt;em&gt;aquí utilizaremos anglicismos&lt;/em&gt; 😜) es una estructura de datos lineal, compuesta por objetos llamados &lt;strong&gt;Nodos&lt;/strong&gt;, los cuales están referenciados unos con otros y no necesariamente porque estén ubicados continuamente en bloques de memoria, como pasa tradicionalmente con los &lt;a href="https://www.ecured.cu/Arreglos_(Inform%C3%A1tica)" rel="noopener noreferrer"&gt;Arrays&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Ahora con cucharita 😅: toda la información volátil (&lt;em&gt;que no está almacenada para siempre, sólo mientras corra nuestro código&lt;/em&gt;) de nuestra aplicación, así como las variables y objetos, se colocan en un espacio de nuestra &lt;a href="https://es.wikipedia.org/wiki/Memoria_vol%C3%A1til" rel="noopener noreferrer"&gt;memoria volátil&lt;/a&gt; (&lt;em&gt;como la RAM&lt;/em&gt;), en el caso de los arreglos, se colocan todos los integrantes uno al lado del otro en &lt;a href="https://es.wikipedia.org/wiki/Asignaci%C3%B3n_de_memoria" rel="noopener noreferrer"&gt;bloques de memoria&lt;/a&gt; continuos. Por ejemplo, supongamos que se tiene lo siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;frutas = ['pizza', 'banana', 'naranja', 'pera', 'piña', 'melón']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;La 🍕 no es una fruta pero a veces le echan tanta piña que parece una&lt;/em&gt; 😪.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;La manera como se aloja en bloques de memoria continuos es la siguiente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xnz3j0q3p46o5bmmj1e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xnz3j0q3p46o5bmmj1e.png" alt="Alt Text" width="497" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nota&lt;/strong&gt;: en la imagen se asume que los caracteres están codificados en &lt;a href="https://es.wikipedia.org/wiki/ISO/IEC_10646#Formas_de_codificar_el_Conjunto_Universal_de_Caracteres" rel="noopener noreferrer"&gt;UCS-4&lt;/a&gt;, lo que implica que se ocupan 4 bytes por caracter.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En el caso de las Linked List, no es necesario, sino, que los integrantes (o Nodos) de dicha lista pueden estar en bloques de memoria bastante alejados o bastante cerca:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0alfypwk1cpk4j4phko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0alfypwk1cpk4j4phko.png" alt="Alt Text" width="497" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si, ya sé... Te estás preguntando que quiere decir eso, déjame ilustrarte:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmstjz6nu4itwzctsf6nt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmstjz6nu4itwzctsf6nt.png" alt="Alt Text" width="697" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hasta este punto tenemos una explicación más clara que concluye en que las Linked List son un grupo de Nodos que se referencian entre sí. Sin embargo, falta un detalle importante, bueno, dos detalles importantes 😅. Lo primero es que nuestro objeto de Linked List no almacena por si solo los Nodos, sino que esta guarda una referencia sólo al primer Nodo, el cual se llama &lt;em&gt;Head&lt;/em&gt; (o cabeza). El &lt;em&gt;Head&lt;/em&gt;, a su vez guarda referencia al Nodo siguiente, y así mismo el Nodo siguiente al que le sigue, hasta llegar al último, el cual tiene que apuntar a una dirección de &lt;a href="https://es.wikipedia.org/wiki/Null" rel="noopener noreferrer"&gt;memoria vacía o de valor nulo&lt;/a&gt;, esto es porque en una Linked List todos los Nodos deben de estar apuntando a "algo".&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cbz5izfm18sj5o8krtz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cbz5izfm18sj5o8krtz.png" alt="Alt Text" width="800" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ya que sabemos más o menos los fundamentos, te estarás preguntando sobre las ventajas de sobre las Listas o Arrays, bueno, realmente existen ciertas ventajas que murieron con la utilización de los &lt;a href="https://moonantonio.github.io/post/2018/dev/004/" rel="noopener noreferrer"&gt;lenguajes de alto nivel&lt;/a&gt;, ya que estos en su mayoría son capaces de ajustar dinámicamente los tamaños de los bloques de memoria, ya que tradicionalmente eran fijos, también permiten tener objetos de diferentes tipos en una misma estructura. No obstante, la verdadera ventaja de esta estructura es el acceso secuencial de la data, lo cual facilita la implementación de otras estructuras muy importantes que veremos más adelante. Ya verás :twink:.&lt;/p&gt;

&lt;p&gt;Podemos hacer muchas operaciones como las Linked List, así como insertar elementos, buscar elementos, entre otras más. Sin embargo, la más importante es la de recorrer la Linked List, ya que todas las demás se apoyan en esta, es decir, siempre hay que recorrer la Linked List. Si quieres saber sobre más operaciones que se pueden hacer con las Linked List, te invito a &lt;a href="https://www.tutorialspoint.com/data_structures_algorithms/linked_list_algorithms.htm" rel="noopener noreferrer"&gt;ver esto&lt;/a&gt;. También existen otras &lt;a href="https://es.wikipedia.org/wiki/Lista_enlazada#Tipos_de_listas_enlazadas" rel="noopener noreferrer"&gt;variantes de Linked List&lt;/a&gt;, son fáciles de entender si se aplican los conceptos explicados anteriormente, sin embargo, no las estaremos utilizando a lo largo de esta serie y por eso no me detendré a explicarlas. Si tu aplicación demanda dichas implantaciones, entonces adelante.&lt;/p&gt;
&lt;h2&gt;
  
  
  Haciendo nuestra propia LinkedList
&lt;/h2&gt;

&lt;p&gt;Cabe destacar que la Estructura de Datos &lt;a href="https://devcode.la/tutoriales/listas-python/" rel="noopener noreferrer"&gt;List&lt;/a&gt; de Python, puede utilizarse como una Linked List, de hecho tiene métodos para tales fines, también tenemos un módulo llamado &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-use-the-collections-module-in-python-3-es#usar-deque-para-a%C3%B1adir-elementos-de-forma-eficiente-a-cada-lado-de-una-colecci%C3%B3n" rel="noopener noreferrer"&gt;Collections&lt;/a&gt; que contiene una Estructura llamada &lt;em&gt;Deque&lt;/em&gt;, la cual funciona parecido. En nuestro caso, haremos la nuestra para fines de explicación de la implementación. En la vida real, estas estructuras ya construidas por el lenguaje que utilicemos nos ahorran tiempo y son más eficientes.&lt;/p&gt;

&lt;p&gt;Primero, empezamos creando los Nodos, estos serán los objetos que almacenaremos en nuestra Linked List, &lt;em&gt;ej.: Pizza, banana, pera, etc.&lt;/em&gt;. La estrategia es que el Nodo pueda hacer referencia al objeto que tendrá como valor y al Nodo siguiente.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Hasta aqui no creo que la cosa se complique 😬. Tenemos un objeto Nodo que posee un valor y una referencia de quien le sigue. Por lo tanto, si yo creo un Nodo, le doy su valor y el del Nodo que le sigue, si no tienen ningún otro, entonces apunta a &lt;code&gt;None&lt;/code&gt;, así voy creando mi Linked List.&lt;/p&gt;

&lt;p&gt;Ok, obvio que no es todo... ¿Cómo puedo saber cual es el &lt;em&gt;Head&lt;/em&gt; de mi lista?... No puedo poner dicho objeto Hardcoded en mi código porque si cambia en alguna parte de este, tendré un tremendo lío con la referencia. Por lo tanto, tenemos que crear un objeto Linked List que siempre guarde una referencia en el atributo Head (&lt;em&gt;tal como lo habíamos dicho antes&lt;/em&gt;) y también efectué todas las operaciones necesarias sobre la lista, tales como recorrerla, voltearla, añadir otros Nodos, extraerlos, etc.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LinkedList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="c1"&gt;# Referencia al nodo head
&lt;/span&gt;    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;

    &lt;span class="c1"&gt;# Si se pasó una lista como argumento, se crea una Linked List
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Selecciona el primer elemento de la lista como la cabeza
&lt;/span&gt;      &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
      &lt;span class="n"&gt;current_node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;

      &lt;span class="n"&gt;list_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;# Itera sobre la lista, si el elemento en curso es el ultimo
&lt;/span&gt;      &lt;span class="c1"&gt;# apunta su siguiente nodo a None
&lt;/span&gt;      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;list_len&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;current_node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;list_len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="n"&gt;current_node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="n"&gt;current_node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;

  &lt;span class="c1"&gt;# Magic method para recorrer la Linked List
&lt;/span&gt;  &lt;span class="c1"&gt;# Este metodo se llama cuando se está recorriendo la Linked List
&lt;/span&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__iter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;
    &lt;span class="c1"&gt;# Retorna cada nodo en la iteración correspondiente
&lt;/span&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;
      &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;

  &lt;span class="c1"&gt;# Magic method que retorna la longitud de la lista
&lt;/span&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__len__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="c1"&gt;# Itera la Linked List mientras cuenta cada elemento
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;

  &lt;span class="c1"&gt;# Magic method que retorna el nodo, dado un indice a la entrada 
&lt;/span&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__getitem__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="c1"&gt;# Retorna el valor del nodo si el item es un entero
&lt;/span&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;
      &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;

  &lt;span class="c1"&gt;# Inserta un nodo al final de la Linked List
&lt;/span&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;#Si no hay nodo, entonces lo inserta como Head
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;
      &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="c1"&gt;# Busca el último nodo y lo apunta al nodo a insertar
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;
        &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Podemos añadir más métodos para hacer más operaciones con nuestra Linked List, pero lo vamos a dejar hasta ahí por el momento para no crearte un Stackoverflow 😫 😵 en el 🧠. La idea es que entiendas el concepto de esta estructura, las demás operaciones las estaremos viendo conforme salgan los otros posts.&lt;/p&gt;
&lt;h2&gt;
  
  
  Aplicando lo aprendido
&lt;/h2&gt;

&lt;p&gt;Para poner en práctica lo explicado anteriormente, vamos a utilizar nuestro código y haremos un reproductor de tracklists como el de Spotify (&lt;em&gt;más sencillo&lt;/em&gt;). En dado caso que no quieras utilizar lo que se creó más arriba, puedes utilizar las estructuras nativas de Python que te mencioné y tomarlo como ejercicio, esto si no sabes sobre POO, más adelante haré una serie al respecto.&lt;/p&gt;

&lt;p&gt;Para esto, consumiremos un &lt;a href="https://www.redhat.com/es/topics/api/what-are-application-programming-interfaces" rel="noopener noreferrer"&gt;API&lt;/a&gt; de &lt;a href="https://www.discogs.com/developers" rel="noopener noreferrer"&gt;Discogs&lt;/a&gt; que nos proporcione los tracklist de acuerdo a releases de los artistas, elegiremos cual queremos reproducir y podremos cambiar de canción o &lt;em&gt;track&lt;/em&gt; (&lt;em&gt;avanzar a la siguiente y/o volver a la anterior&lt;/em&gt;).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nota&lt;/strong&gt;: esto no es un tutorial para consumir APIs, esta parte la puedes obviar, te puedes hacer de cuenta que es una función que llamas y te da una lista de tracks. De todos modos, pondré el código por si alguien se anima a querer entenderlo, no tiene mucha complejidad&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sample&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_tracklists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;artist_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;57620&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;releases_n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Url para obtener los releases 
&lt;/span&gt;  &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.discogs.com/artists/{}/releases&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;artist_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;releases&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;releases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;release&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;master&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="c1"&gt;# Filtrando la data y obteniendo el campo de releases
&lt;/span&gt;  &lt;span class="n"&gt;random_rels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;releases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;releases_n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

  &lt;span class="c1"&gt;# Url para obtener información acerca de los releases
&lt;/span&gt;  &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.discogs.com/masters/{}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
  &lt;span class="n"&gt;tracklists_names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

  &lt;span class="c1"&gt;# Separando los tracklist de cada reseale
&lt;/span&gt;  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;rel&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;random_rels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;tracklists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tracklist&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="c1"&gt;# Tiempo de delay para que api.discogs.com no niegue los responses
&lt;/span&gt;    &lt;span class="c1"&gt;# debido a la velocidad en un corto lapso de tiempo
&lt;/span&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;tracklists_names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tracklists&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type_&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;track&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]})&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tracklists_names&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;En resumen, la funcion retorna una lista con varios diccionarios, en los cuales cada &lt;em&gt;key&lt;/em&gt; es el nombre de un &lt;em&gt;release&lt;/em&gt; en específico de un artista en específico (&lt;em&gt;para el ejemplo he cogido a &lt;a href="https://es.wikipedia.org/wiki/Buddy_Rich" rel="noopener noreferrer"&gt;Buddy Rich&lt;/a&gt;&lt;/em&gt;), el value de cada uno sería una lista de las canciones o &lt;em&gt;tracks&lt;/em&gt; pertenecientes a dicho &lt;em&gt;release&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Para crear nuestra app de nuestro reproductor, tendríamos lo siguiente:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apis&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_tracklists&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;linked_list&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LinkedList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;app&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="c1"&gt;# Obtiene la lista de los releases con sus repectivos tracklists
&lt;/span&gt;  &lt;span class="n"&gt;releases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_tracklists&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;current_rel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_track&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;No release selected&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;No track selected&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;#Linked List para manejar los tracks
&lt;/span&gt;  &lt;span class="n"&gt;tracklist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LinkedList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;# String de las opciones del menu
&lt;/span&gt;  &lt;span class="n"&gt;main_menu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;

Main menu 
===================

1. Select Release
2. Next track
3. Previous track
4. Exit
Current Release: {}
Current Track: {}

Select an option: &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Guarda la opcion seleccionada en el menu
&lt;/span&gt;    &lt;span class="n"&gt;selection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main_menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_rel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;selection&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Construye el menu de releases
&lt;/span&gt;      &lt;span class="c1"&gt;# Para fines de este tutorial, no se abundará esta parte
&lt;/span&gt;      &lt;span class="n"&gt;rel_menu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;rel_list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{}- {} &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rel&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rel_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;rel_list&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
      &lt;span class="n"&gt;releases_menu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;

Releases Menu
=====================

{}

Select an option: &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

      &lt;span class="c1"&gt;# Captura la selección del release
&lt;/span&gt;      &lt;span class="n"&gt;release_selection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;releases_menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rel_menu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;releases&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

      &lt;span class="c1"&gt;# Guarda el release seleccionado en el menu
&lt;/span&gt;      &lt;span class="c1"&gt;# El release contiene una lista con los tracklist
&lt;/span&gt;      &lt;span class="n"&gt;rel_dic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;releases&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;release_selection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;rel_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rel_dic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;rel_tracks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rel_dic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

      &lt;span class="c1"&gt;# Actualiza la Linked List a una con el tracklist seleccionado 
&lt;/span&gt;      &lt;span class="n"&gt;tracklist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LinkedList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rel_tracks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;# Asigna los valores para el release seleccionado,
&lt;/span&gt;      &lt;span class="c1"&gt;# y el track en reproduccion como el head de la Linked List
&lt;/span&gt;      &lt;span class="n"&gt;current_rel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_track&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rel_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tracklist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;

    &lt;span class="c1"&gt;# Para cambiar al siguiente solo se asigna el nodo siguiente al track actual
&lt;/span&gt;    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;selection&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;current_track&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;

    &lt;span class="c1"&gt;# Para volver atrás se recorre la lista hasta que el nodo siguiente
&lt;/span&gt;    &lt;span class="c1"&gt;# del iterado sea el del track actual 
&lt;/span&gt;    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;selection&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tracklist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;current_track&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="n"&gt;current_track&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;

    &lt;span class="c1"&gt;# Sale de la aplicación
&lt;/span&gt;    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;selection&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;4&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

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

&lt;p&gt;La Linked List es una estructura muy poderosa y una alternativa a otras que ya conocemos, sobre todo son útiles en aplicaciones que utilizamos en el día a día, incluyendo los protocolos que se utilizan en nuestros equipos de redes, pero eso no es tema de este post, iremos adentrándonos más adelante.&lt;/p&gt;

&lt;p&gt;Te dejo el código en Repl.it del resultado final para que puedas correrlo tu mismo.&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@Jorgmassih/Linked-List-tutorial?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/jorgmassih" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.buymeacoffee.com%2Fbutton-api%2F%3Ftext%3DBuy%2520me%2520a%2520coffee%2520here%26emoji%3D%25E2%258C%25A8%25EF%25B8%258F%26slug%3Djorgmassih%26button_colour%3D5F7FFF%26font_colour%3Dffffff%26font_family%3DLato%26outline_colour%3D000000%26coffee_colour%3DFFDD00" width="280.0" height="50"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>networking</category>
      <category>linkedlist</category>
      <category>datastructure</category>
      <category>python</category>
    </item>
    <item>
      <title>Estructuras de Datos para Network Engineers 101: Introducción</title>
      <dc:creator>Jorge Massih</dc:creator>
      <pubDate>Mon, 12 Apr 2021 04:11:29 +0000</pubDate>
      <link>https://dev.to/plusiv/estructura-de-datos-para-network-engineers-101-introduccion-4j0k</link>
      <guid>https://dev.to/plusiv/estructura-de-datos-para-network-engineers-101-introduccion-4j0k</guid>
      <description>&lt;p&gt;Hoy en día, tres conceptos están tomando auge en el mundo del &lt;em&gt;Networking&lt;/em&gt; y &lt;em&gt;IT&lt;/em&gt;: Software Defined Network (ó Redes Definidas Por Software), Network Automation (ó Automatización de Redes) y Network Orquestation (u Orquestación de Redes). Estos se pueden involucrar entre sí, sin embargo, &lt;a href="https://etherealmind.com/difference-sdn-automation-orchestraton/" rel="noopener noreferrer"&gt;sería un pecado capital confundirlos&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Debido a los nuevos paradigmas emergentes, muchos ingenieros se han tenido que tomar la tarea de aprender a programar. No todo es tan fácil a la hora de hacer este trabajo, existen conocimientos que debemos tener para que el proceso no resulte tan frustrante a la hora de diseñar una aplicación y verla funcionando, me refiero a conocimientos acerca de &lt;a href="https://concepto.de/algoritmo-en-informatica" rel="noopener noreferrer"&gt;Algoritmos&lt;/a&gt; y Estructura de Datos, esta última, según &lt;a href="https://www.geeksforgeeks.org/data-structures/" rel="noopener noreferrer"&gt;GeeksForGeeks&lt;/a&gt;, no es más que una forma particular de organizar los datos en una computadora, de manera que estos puedan ser accedidos y utilizados de una manera &lt;strong&gt;eficiente&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A veces solemos queremos automatizar tareas en nuestra red, o también brindar un servicio que utilice la automatización como medio operativo, o tal vez quisiéramos implementar nuestra propia versión del protocolo &lt;a href="https://es.wikipedia.org/wiki/Open_Shortest_Path_First" rel="noopener noreferrer"&gt;OSPF&lt;/a&gt; o del &lt;a href="https://es.wikipedia.org/wiki/Spanning_tree" rel="noopener noreferrer"&gt;STP&lt;/a&gt;, hasta nuestra propia aplicación de &lt;a href="https://es.wikipedia.org/wiki/Calidad_de_servicio" rel="noopener noreferrer"&gt;QoS&lt;/a&gt;. Para hacer todas estas cosas es necesario conocer &lt;strong&gt;Estructuras de Datos&lt;/strong&gt; como Linked List, Queues, Stacks, Hash Tables, Graphs, Binary Trees, entre otras más. Afortunadamente, este es el primer post de otros más que vendrán en esta serie llamada &lt;em&gt;Estructuras de Datos para Network Engineers 101&lt;/em&gt;, y estas estructuras ya mencionadas las estaremos viendo a lo largo del camino. Es bueno aclarar que no profundizaré a tal nivel que termines siendo un experto en el manejo de esas estructuras que te mencioné, pero si tendrás fundamentos sólidos para llegar a serlo con tu propia práctica.&lt;/p&gt;

&lt;p&gt;Te pongo un ejemplo que quizás te motive a seguir leyendo: supón que estás automatizando una tarea en tu red, y en un fragmento de tu código necesitas filtrar una lista de IPs que pueda contener las mismas IPs más de una vez, de modo que las IPs no se repitan. Si tu primer approach sería hacer algo más o menos como lo que vamos a hacer a continuación, entonces esta serie es ideal para ti. Si pensaste en una manera más óptima de resolver el problema, también, te invito que te quedes, quizás aprendas algo nuevo más adelante, nadie sabe 😉.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# No tan cool :p
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;remove_duplicated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;filtered_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;filtered_list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;filtered_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;filtered_list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;En pocas palabras lo que se intenta hacer es &lt;em&gt;recorrer la lista e ir almacenando cada Ip en otra lista nueva, si esta Ip ya está almacenada, entonces no se añade&lt;/em&gt;. Realmente el algoritmo es correcto, y va a funcionar, el problema es que en el mundo del software no es suficiente con que el las aplicaciones solamente funcionen, sino que también sean eficientes a nivel de rendimiento. La idea es que tu código corra lo más óptimo posible cuando tenga entradas de miles de datos y necesite entrar a decenas de equipos en tu red de una manera muy rápida.&lt;/p&gt;

&lt;p&gt;A continuación, te mostraré la razón de la ineficiencia del algoritmo concebido, pero no te asustes si no entiendes, no utilizaremos este método a lo largo de la serie ya que trataré de explicarte todo con cucharita y de la forma más clara y resumida posible. Cabe destacar que sí es importante que te tomes un tiempo para aprender a analizar algoritmos, lo agradecerás en un futuro.&lt;/p&gt;

&lt;p&gt;Usando el &lt;a href="https://medium.com/@_SD10_/the-ram-model-of-computation-and-big-o-notation-a1b3cc50ec2c" rel="noopener noreferrer"&gt;Modelo de la RAM&lt;/a&gt; para analizar el tiempo de ejecución, tenemos que.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Instrucción&lt;/th&gt;
&lt;th&gt;Veces que se repite&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;filtered_list = []&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;


&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;11 &lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;for ip in l&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;nn &lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;if ip not in filtered_list&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;n(n+1)2\frac{n(n+1)}{2}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;n&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;n&lt;/span&gt;&lt;span class="mbin mtight"&gt;+&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;filtered_list.append(ip)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;n(n+1)2\frac{n(n+1)}{2}&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;n&lt;/span&gt;&lt;span class="mopen mtight"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;n&lt;/span&gt;&lt;span class="mbin mtight"&gt;+&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;span class="mclose mtight"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;return filtered_list&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;11 &lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;T(n)=n(n+1)2+n(n+1)2+n+1+1T(n) = \frac{n(n+1)}{2} + \frac{n(n+1)}{2} + n + 1 + 1  &lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;T(n)=n(n+1)+n+2T(n) = n(n+1) + n + 2  &lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;T(n)=n2+2n+2T(n) = n^2 + 2n + 2  &lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nota&lt;/strong&gt;: Cada instrucción está asociada a un costo (
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;cic_i &lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;c&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
), el cual no es más que una cantidad de pasos que toma para ejecutarse, pero para fines de explicación lo vamos a obviar asumiendo que es 1 para todas las instrucciones, esto para no complicar el asunto.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Si analizamos el &lt;a href="https://es.wikipedia.org/wiki/Complejidad_temporal" rel="noopener noreferrer"&gt;Time Complexity (ó Complejidad Temporal)&lt;/a&gt; de nuestro algoritmo obtendremos que es una &lt;a href="https://guias.makeitreal.camp/algoritmos/complejidad#complejidad-exponencial-o-n-2-o-n-3-etc" rel="noopener noreferrer"&gt;Complejidad Exponencial&lt;/a&gt; de tipo 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(n)=n2O(n) = n^2 &lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.&lt;/p&gt;

&lt;p&gt;Existe una mejor manera, incluso, el algoritmo es más simple y corre en una &lt;a href="https://guias.makeitreal.camp/algoritmos/complejidad#complejidad-lineal-o-n" rel="noopener noreferrer"&gt;Complejidad Lineal&lt;/a&gt; de tipo 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;O(n)=nO(n) = n &lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# muy cool :p
&lt;/span&gt;&lt;span class="n"&gt;filtered_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Dependiendo de las operaciones que necesitemos hacer sobre
# el iterable, podemos olvidarnos de convertir el set a lista.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta mejora en nuestro algoritmo se debe a que se supo utilizar una estructura de datos adecuada para los fines, la cual está basada en &lt;a href="https://es.wikipedia.org/wiki/Conjunto" rel="noopener noreferrer"&gt;conjuntos numéricos&lt;/a&gt;, esta es denominada &lt;a href="https://tutorialedge.net/compsci/data-structures/sets-for-beginners/" rel="noopener noreferrer"&gt;Set&lt;/a&gt;. No vamos a hablar mucho ahora de esta Estructura de Datos, por lo que sólo nos quedaremos sabiendo que no permite elementos repetidos en ella.&lt;/p&gt;

&lt;p&gt;Si no has entendido nada de lo que se explicó arriba sobre &lt;em&gt;Big O Notation&lt;/em&gt;, &lt;em&gt;Time Complexity&lt;/em&gt; y/o &lt;em&gt;Time Execution&lt;/em&gt;, entonces tienes mucho que leer. &lt;a href="https://www.amazon.com/-/es/Thomas-H-Cormen-ebook-dp-B08FH8N996/dp/B08FH8N996/ref=mt_other?_encoding=UTF8&amp;amp;me=&amp;amp;qid=" rel="noopener noreferrer"&gt;Te recomiendo este libro para iniciar&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mientras tanto, en lo que el hacha va y viene, te lo voy a explicar de una manera sencilla: El primer algoritmo concebido es ineficiente delante del segundo. ¡Listo!. Esto es culpa de la Estructura de Datos seleccionada, ya que el algoritmo que concibamos dependerá mucho de esto. Y no es que sea una mala Estructura de Datos, lo que pasa es que no es la más adecuada para los fines.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;my_ips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;192.168.1.1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;192.168.1.2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;192.168.2.1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;192.168.2.2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;192.168.3.1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;192.168.3.2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;192.168.4.1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;192.168.4.2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;192.168.5.1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;192.168.5.1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;remove_duplicated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_ips&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Tiempo en segundos
&lt;/span&gt;&lt;span class="mf"&gt;0.0016276000000061686&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_ips&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Tiempo en segundos
&lt;/span&gt;&lt;span class="mf"&gt;0.0004897999999684544&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nota&lt;/strong&gt;: En este ejemplo se utilizaron las condiciones para recrear el peor caso de ejecución para el algoritmo, es decir, donde no se repite ninguna IP y este tenga que correr todas las instrucciones.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pudimos ver como tomamos de ejemplo 10 IPs y se nota la diferencia en el tiempo de ejecución, de hecho, no es más grande porque la cantidad IPs de entrada es relativamente pequeña comparada con miles que nuestro código pudiera recibir. &lt;/p&gt;

&lt;p&gt;Por esto es importante saber sobre Estructuras de Datos, pueden hacer más ligeras las cosas, también, nos ayudan a concebir buenos algoritmos para tratar los problemas de una manera más fácil. &lt;/p&gt;

&lt;p&gt;Voy a tratar de enseñarte a través de ejemplos prácticos, la mayoría de estos aplicados al mundo del &lt;em&gt;Networking&lt;/em&gt;, publicaré el código de lo que vamos a hacer en cada post y te explicaré cómo funciona, fragmento por fragmento, de una manera resumida claro está. La idea es que no dures demasiado leyendo un post que te vaya a agobiar, sería mejor que pases más tiempo profundizando por tu parte lo que voy a explicar, esto lo harás con los fundamentos que te enseñaré en cada post. Trataré de utilizar un lenguaje muy llano y divertido, para que no te canses si no entiendes algo, además, cualquier duda que tengas puede ser depositada en los comentarios y yo me tomaré de vez en cuando el tiempo para responderlas.&lt;/p&gt;

&lt;p&gt;Entonces, si tengo tu atención, te recomiendo el siguiente post, el cual dará inicio formal a la serie y te introducirá a la primera Estructura de Datos a tratar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/jorgmassih" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.buymeacoffee.com%2Fbutton-api%2F%3Ftext%3DBuy%2520me%2520a%2520coffee%2520here%26emoji%3D%25E2%258C%25A8%25EF%25B8%258F%26slug%3Djorgmassih%26button_colour%3D5F7FFF%26font_colour%3Dffffff%26font_family%3DLato%26outline_colour%3D000000%26coffee_colour%3DFFDD00" width="280.0" height="50"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>networking</category>
      <category>datastructure</category>
      <category>programming</category>
      <category>python</category>
    </item>
  </channel>
</rss>
