{"id":3775,"date":"2016-03-27T12:22:45","date_gmt":"2016-03-27T16:22:45","guid":{"rendered":"http:\/\/kodegeek.com\/blog\/?p=3775"},"modified":"2016-03-27T12:23:14","modified_gmt":"2016-03-27T16:23:14","slug":"decoracion-de-funciones-en-python-usando-functools","status":"publish","type":"post","link":"http:\/\/kodegeek.com\/blog\/2016\/03\/27\/decoracion-de-funciones-en-python-usando-functools\/","title":{"rendered":"Decoraci\u00f3n de funciones en Python usando functools"},"content":{"rendered":"<p>La decoraci\u00f3n de funciones, usando <a href=\"https:\/\/docs.python.org\/2\/library\/functools.html\" target=\"_blank\">functools<\/a>, en Python nos permite eliminar c\u00f3digo repetitivo que debemos escribir una y otra vez, y tambi\u00e9n nos permite modificar funciones existentes con unas pocas lineas de c\u00f3digo. Como ejemplo, veamos la tuber\u00eda que escrib\u00ed hace tiempo atr\u00e1s:<\/p>\n<pre lang=\"python\">\r\n#!\/usr\/bin\/env python3\r\nimport sys, re\r\n\r\ndef grep(expression):\r\n    while True:\r\n        text = (yield)\r\n        if re.search(expression, text):\r\n            print(text)\r\n\r\ndef cat(file, target):\r\n    next(target)\r\n    with open(file, \"r\") as fh:\r\n        for line in fh.readlines():\r\n            target.send(line.strip())\r\n\r\ndef main(args):\r\n    cat(args[0], grep(args[1]))\r\n\r\nif __name__ == \"__main__\":\r\n    main(sys.argv[1:])\r\n<\/pre>\n<p>En la linea 11 pueden ver que hay que preparar el otro lado de la tuber\u00eda antes de enviar datos, lo cual es un fastidio; Usando &#8216;functools&#8217; podemos crear una anotaci\u00f3n a la medida, la cual llamaremos &#8216;pipe&#8217; (lineas 6-12):<\/p>\n<pre lang=\"python\">\r\n#!\/usr\/bin\/env python3\r\n# Shows how to use a function decorator to create an annotation\r\n# josevnz@kodegeek.com\r\nimport sys, re, functools\r\n\r\ndef pipe(function):\r\n    @functools.wraps(function)\r\n    def wrapper(*args, **kwargs):\r\n        target = function(*args, **kwargs)\r\n        next(target) # Saves us the trouble of calling next on the pipe\r\n        return target\r\n    return wrapper\r\n\r\n@pipe\r\ndef grep(expression):\r\n    while True:\r\n        text = (yield)\r\n        if re.search(expression, text):\r\n            print(text)\r\n\r\ndef cat(file, target):\r\n    with open(file, \"r\") as fh:\r\n        for line in fh.readlines():\r\n            target.send(line.strip())\r\n\r\ndef main(args):\r\n    cat(args[0], grep(args[1]))\r\n\r\nif __name__ == \"__main__\":\r\n    main(sys.argv[1:])\r\n<\/pre>\n<p>En la l\u00ednea 14 agregamos la nueva anotaci\u00f3n y note como eliminamos el &#8216;next(target)&#8217; completamente de la funci\u00f3n cat(file, target). No paree gran cosa, pero es una l\u00ednea menos de c\u00f3digo que poner en cada llamada.<\/p>\n<p>\u00bfPero se pueden hacer otras cosas? Se me ocurren decoraciones como &#8216;count&#8217; o &#8216;sorted&#8217; para funciones que trabajan con listas, estoy aprendiendo como usar esta nueva herramienta, ya les dir\u00e9 como me va.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>La decoraci\u00f3n de funciones, usando functools, en Python nos permite eliminar c\u00f3digo repetitivo que debemos escribir una y otra vez, y tambi\u00e9n nos permite modificar funciones existentes con unas pocas lineas de c\u00f3digo. Como ejemplo, veamos la tuber\u00eda que escrib\u00ed hace tiempo atr\u00e1s: #!\/usr\/bin\/env python3 import sys, re def grep(expression): while True: text = (yield) <a class=\"read-more\" href=\"http:\/\/kodegeek.com\/blog\/2016\/03\/27\/decoracion-de-funciones-en-python-usando-functools\/\">[&hellip;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[194,239],"tags":[803,802,804,765],"_links":{"self":[{"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/posts\/3775"}],"collection":[{"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/comments?post=3775"}],"version-history":[{"count":5,"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/posts\/3775\/revisions"}],"predecessor-version":[{"id":3780,"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/posts\/3775\/revisions\/3780"}],"wp:attachment":[{"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/media?parent=3775"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/categories?post=3775"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/kodegeek.com\/blog\/wp-json\/wp\/v2\/tags?post=3775"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}