O, "cosas que nunca deberías hacer en producción" El otro día, estaba mirando un código de Python que estaba compuesto por una secuencia de llamadas a funciones profundamente anidadas y un pensamiento inmediatamente subió a la pila del cerebro: ¿No sería genial si Python tuviera un operador similar al de Elixir? operador de tubería ¿Operador de tuberías? Para aquellos de ustedes que no están familiarizados con Elixir, el operador de canalización se puede usar para convertir un código que se ve así: |> Llamadas a funciones anidadas. En un código que se ve así: ¡Refrescante! En esencia, el operador de tubería toma la expresión de su lado izquierdo y la mueve a la posición del primer argumento de la expresión de su lado derecho, asumiendo que la expresión de la derecha es una llamada de función. Haciéndolo en Python Aunque no es posible agregar un operador de tubería real al lenguaje sin cambiar el intérprete de Python, ¡no hay nada que nos impida reutilizar un operador existente! Eso es exactamente lo que me propuse hacer. Tomando prestado de los shells, pensé que el operador "bit a bit o" (también conocido como "tubería") sería una buena opción para este tipo de funcionalidad: La forma más sencilla que se me ocurrió para reutilizar el operador de tubería fue reescribir funciones usando un decorador. El módulo incorporado de Python hace que esto sea particularmente fácil. ast Todo lo que tenía que hacer era obtener el código fuente de una función (usando ), inspect.getsource conviértalo en un árbol de sintaxis abstracto pasándolo a , ast.parse camine por el árbol y transforme cualquier ocurrencia del operador de tubería de acuerdo con las reglas que describí al final de la última sección y, finalmente, compile y devuelva el objeto de función reescrito. Eso suena mucho más complicado de lo que resulta ser en la práctica. El módulo proporciona una clase llamada que implementa el patrón de visitante: su método de realiza una búsqueda en profundidad a través de un AST y llama a cualquier método declarado de la forma en sí mismo para cada nodo en el árbol. Como su nombre lo indica, puede usar un transformador de nodos para visitar y manipular los nodos de un AST: ast NodeTransformer visit visit_NODETYPE Cada vez que el transformador encuentra un operador binario, recurre para que las transformaciones que deben realizarse en sus nodos izquierdo y derecho se realicen primero, luego verifica si el operador actual es "bit a bit o". Si el operador del nodo actual es "bit a bit o" y si el lado derecho es un nodo de llamada de función, entonces inserta el lado izquierdo en la posición del primer argumento de la llamada de función y luego devuelve el nodo de la derecha lado, reemplazando el nodo del operador binario con el nodo de llamada en el árbol. El transformador también se activa cuando ve una definición de función para que pueda eliminar el decorador . Esto tendrá sentido una vez que eches un vistazo al decorador en sí: enable_threadop El decorador toma una función como argumento, toma su código fuente y elimina cualquier sangría (¡esto es importante! De lo contrario, los métodos de decoración de clase dan como resultado un ), analiza el código y transforma el AST y, finalmente, compila y ejecuta la función. definición, devolviendo el objeto de función resultante. SyntaxError Si el transformador no hubiera eliminado el decorador del árbol final, tendríamos un bucle infinito en nuestras manos porque se llamaría a una y otra vez cuando se ejecuta la definición de la función (línea 13). enable_threadop Con todo eso en su lugar, el decorador se puede usar para cambiar selectivamente el comportamiento del operador de tubería: enable_threadop Si ese no es un ejemplo realista, ¡no sé qué lo es! Limitaciones Como era de esperar, hay un par de limitaciones con este enfoque. En primer lugar, el código fuente de las funciones del sistema de archivos, lo que significa que el decorador no funcionará en el intérprete de Python. inspect.getsource En segundo lugar, el transformador requiere que el lado derecho del operador de tubería sea una llamada de función. ¡Es hora de usarlo en producción! ¡Vaya, más despacio! ¡Este es solo un pequeño experimento genial y definitivamente no es algo que deba infligir a sus compañeros de trabajo! Dicho esto, si quieres jugar con él, puedes encontrar el código completo (¡50 líneas con comentarios!) en . GitHub ¡Gracias por leer! Si te ha gustado el artículo, ¡dale un aplauso! También puede encontrarme en mi sitio web en https://defn.io , en GitHub y Twitter . _Los últimos Tweets de Bogdan Popa (@bogdanp). Programador, creador de https://t.co/FFd6cPhKk5 y…_twitter.com Bogdan Popa (@bogdanp) | Twitter