Uso De Pipes En Python

Fecha de publicaci贸n: 1 Noviembre 2021
Tiempo de lectura: 5 min.
Premium: False
N煤mero de visitas: 209


Hace un par de post hablamos acerca de las funciones an贸nimas en Python y sobre la programaci贸n funcional con este lenguaje (Si aun no los haz le铆do te los recomiendo encarecidamente). Pues bien, para complementar dichos post, en esta ocasi贸n me gustar铆a habl谩ramos sobre una librer铆a en Python que nos permitir谩 implementar pipes (|). S铆, pipes (|), los mismos que podemos utilizar en sistemas operativos unix. 馃槑

_Si nunca hab铆as escuchado hablar acerca de los pipes, no te preocupes, aqu铆 te compartimos un post en donde te lo explicamos en detalle_. Espero puedas echarla un vistazo.

Este ser谩 un post muy interesante, principalmente si te encuentras enfocado en dar tus primero pasos con la programaci贸n funcional en Python. As铆 que te invito a que te quedes.

Bien, una vez dicho todo esto, y sin m谩s introducci贸n, comencemos con el tutorial. 馃榿

Pipes

Lo primero que debemos saber es que, en Python no es posible implementar los pipes (|) de forma nativa, por lo tanto debemos hacer uso de la librer铆a pipe. Esta librer铆a nos permitir谩 ejecutar una serie de funciones de forma secuencial, tomando el output de una funci贸n como el input de otra.

Para poder hacer uso de la librer铆a lo primero que debemos hacer ser谩 instarla.

pip install pipe

Una vez la libar铆a haya sido instalada, ahora s铆, ya podemos hacer uso de pipes.

Nota: Es importante mencionar que Python posee el m贸dulo pipes en su biblioteca est谩ndar (En plural). M贸dulo que no debe ser confundido con la librer铆a pipe que acabamos de instalar. 馃

La librer铆a pipe se apoya mucho del uso de funciones an贸nimas, lo cual nos viene estupendo si queremos implementar programaci贸n funcional. Veamos un par de ejemplos.

Comencemos con algo sencillo. Por ejemplo, obtengamos todos los n煤meros pares mayores a 10 que se encuentren dentro de un listado.

Utilizando la librer铆a pipe, el c贸digo pudiera quedar de la siguiente manera.

>>> from pipe import where

>>> listado = [4, 6, 8, 10, 9, 11, 34, 12, 15, 16]
>>> resultado = listado | where(lambda x: x > 10)  | where(lambda x: x % 2 == 0)

>>> resultado
 <generator object where>

Es mediante la funci贸n where seremos capaces de filtrar elementos de una colecci贸n, vaya, condicionarlos. Basta con pasar como argumento la funci贸n lambda que deseamos ejecutar. 馃悾

Para este ejemplo he definido funciones lambdas con un solo par谩metro (x), el cual hace referencia a una elemento dentro de la colecci贸n. Teniendo en cuenta que cada funci贸n deber谩 ejecutarse por cada uno de los elementos en la colecci贸n.

La primera condici贸n nos permite obtener todos aquellos elementos mayores a 10, y posteriormente, la segunda condici贸n todos aquellos elementos pares. Condicionamos en 2 ocasiones. De forma secuencial. La salida de la primera funci贸n where es utilizada como la entrada para la segunda funci贸n where.

El resultado ser谩 un objeto de tipo generator. Objeto que f谩cilmente podemos convertir a un listado. utilizando la funci贸n list.

>>> list(resultado)
[34, 12, 16]

_Que de hecho, tambi茅n tenemos una serie de generadores en PyWombat._ 馃嵒

En mi caso 煤nicamente 3 elementos cumplen con la condici贸n, ser mayores a 10 y ser n煤meros pares.

Como podemos observar, el uso de lambdas nos permite dividir el problema en partes peque帽as, pudiendo as铆 construir funciones que realicen una y solo una tarea. Que quiz谩s de forma individual no supongan gran cosa, pero en conjunto logran solventar la problem谩tica.

Ok, ahora, quiz谩s te est茅s preguntando 驴Qu茅 no acaso la funci贸n where hace exactamente lo mismo que la funci贸n filter que Python ya posee? Y la respuesta es s铆. Sin embargo creo que al hacer uso de la funci贸n Where el c贸digo se vuelve mucho m谩s legible, y da pie al poder ejecutar m煤ltiples funciones de forma secuencial, algo que con filter ser铆a un poco complicado. 馃檯鈥嶁檧锔

Bien, y 驴Acaso existe un equivalente para la funci贸n map de Python con pipe? Y de nuevo la respuesta es s铆. Veamos otro ejemplo.

Que te parece si ahora obtenemos el cuadrado de cada uno de los elementos dentro del listado. Para ello haremos uso de la funci贸n select, que ser铆a el equivalente de la funci贸n map en Python.

>>> from pipe import select

>>> resultado = listado | select(lambda x: x ** 2)
>>> list(resultado)
[16, 36, 64, 100, 81, 121, 1156, 144, 225, 256]

Utilizando select podremos aplicar una funci贸n sobre cada uno de los elementos dentro de la colecci贸n. Obteniendo as铆 una nueva colecci贸n con nuevos elementos.

Por supuesto, nosotros podemos combinar tanto la funci贸n select como la funci贸n where.

>>> from pipe import select, where

>>> resultado = listado | select(lambda x: x ** 2) | where(lambda x: x > 100) 
>>> list(resultado)
[121, 1156, 144, 225, 256]

Para este ejemplo generamos un listado con todos aquellos elementos elevados al cuadrado cuyo valor sea mayor que 100.

Bastante cool 驴No lo crees?

Agrupamiento

Lo interesante de la librer铆a pipe no solo recae en el uso de la funci贸n select o where, no para nada, ya que atreves de esta librer铆a seremos capaces, inclusive, de agrupar elementos. S铆, as铆 como lo lees. Esto sin duda me recuerda mucho a LinQ de C#.

Veamos un par de ejemplos.

De mismo listado, generemos 2 grupos. Elementos mayores igual a 10 y elementos menores a 10. El c贸digo pudiera quedar de la siguiente manera.

>>> resultado = listado | groupby( lambda x: "Mayores" if x > 10 else "Menores" )
>>> resultado
<itertools.groupby at 0x7fc1e7316728>

Al utilizar la funci贸n groupby obtendremos como resultado un objeto de tipo iterador.

Este objeto no es m谩s que una colecci贸n de tuplas. Tuplas con 2 elementos. El Id por el cual se realizo el agrupamiento y los elementos agrupados.

Si queremos iterar los elementos agrupado, podemos hacerlo mediante un ciclo for.

Nota: Recordemos que al tratarse de un objeto de tipo iterador, una vez iteremos sobre todos los elementos de dicha colecci贸n, no ser谩 posible reutilizar este iterador una segunda ocasi贸n, por lo tanto solo queda generar nuevamente el agrupamiento. 馃く

>>> resultado = listado | groupby( lambda x: "Mayores" if x > 10 else "Menores" )

>>>  for grupo, elementos in resultado:
    ...:     print(grupo, ':', list(elementos))

Mayores : [11, 34, 12, 15, 16]
Menores : [4, 6, 8, 10, 9]

Para este ejemplo convertimos todos los elementos agrupados en un listado, el cual f谩cilmente podemos manipular, sin embargo recordemos que estos tambi茅n podemos hacerlo utilizando la funci贸n select.

Hagamos un refactor al agrupamiento.

>>> agrupamiento = lambda x: "Mayores" if x > 10 else "Menores"
>>> resultado = listado | groupby( agrupamiento ) | select( lambda x: { x[0]: list(x[1]) }  )
>>>  resultado = list(resultado)

>>> resultado
[{'Mayores': [11, 34, 12, 15, 16]}, {'Menores': [4, 6, 8, 10, 9]}]

Este es sin duda un agrupamiento mucho mejor, ya que dejamos de lado el utilizar iteradores y procedemos a crear un listado de diccionarios. Diccionarios que hacen referencia a cada uno de los grupos creados, y que su vez almacenan los elementos agrupados.

En este caso fueron 2 grupos, sin embargo podemos generar la n cantidad de grupos que deseemos.

Por ejemplo, creemos 3 grupos. Elementos menores a 10, elementos iguales a 10 y elementos mayores a 10. 馃槺

def validador(elemento):
    if elemento > 10:
        return 'Mayores'
    elif elemento == 10:
        return 'Iguales'
    else:
         return 'Menores'

>>> resultado = listado | groupby(validador) | select( lambda x: { x[0]: list(x[1]) }  )
>>> resultado = list(resultado)

[{'Iguales': [10]},
 {'Mayores': [11, 34, 12, 15, 16]},
 {'Menores': [4, 6, 8, 9]}]

En este caso como el agrupamiento requiere de mayor l贸gica he definido la funci贸n validador, Y paso como argumento dicha funci贸n.

Elementos duplicados.

Ya para finalizar el post me gustar铆a mencionar que con la librer铆a pipe seremos capaces de eliminar elementos duplicados de una colecci贸n. Esto gracias a la funci贸n dedup. Funci贸n que sin duda me ha sacado de un par de apuros. 馃悳

>>> from pipe import where, dedup

>>> listado = [4, 6, 8, 10, 9, 11,  12, 12, 12, 11, 12]
>>> resultado = listado | where(lambda x: x > 10)  | dedup(lambda x: x % 2 == 0)
>>> resultado = list(resultado)

>>> resultado
[11, 12]

De igual forma la funci贸n recibe como argumento la funci贸n que debe aplicarse sobre cada uno de los elementos en la colecci贸n.

Si bien esto puede sonar algo trivial, ya que recordemos en Python existen los sets (Colecciones que no permiten elementos duplicados) tambi茅n es importante recordar que estos no puede ser utilizados en una secuencia de ejecuci贸n, como si lo hace dedup. 馃悕

Conclusi贸n

Listo, ahora ya sabes como poder implementar pipes con Python. Sin bien es cierto en esta ocasi贸n trabajamos con un par de funciones de la librer铆a pipe, es importante mencionar que no son las 煤nica. Es por ello que, antes de finalizar la lectura, me gustar铆a compartirte el link del Repositorio Oficial donde es posible conocer m谩s acerca de esta asombrosa herramienta.

Espero el post haya sido de tu agrado, y si fue as铆, no olvides hac茅rnoslo saber en la secci贸n de comentarios. 馃嵒

M谩s Tips y Ejercicios 馃悕

Adquiere una subscripci贸n PyWombat por tan solo $3 USD. al mes.

Conoce los beneficios de ser usuario premium:
Niveles desbloqueados: Ten accesos a todos los niveles de ejercicios. 馃敁
Nuevo l铆mite: Incrementa tu l铆mite de ejercicios por semana. 馃殌
Contenido 煤nico: Recibe semanalmente recursos exclusivos de Python (Videos, Art铆culos y Capitulos del libro PyWombat, comienza como desarrollador Python. 馃悕