<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mundo Geek &#187; lambda</title>
	<atom:link href="http://mundogeek.net/etiqueta/lambda/feed/" rel="self" type="application/rss+xml" />
	<link>http://mundogeek.net</link>
	<description>Mundo geek, bitácora sobre todo lo geek: software, gadgets, tecnología, internet, ...</description>
	<lastBuildDate>Fri, 25 May 2012 14:51:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Python: Programación funcional</title>
		<link>http://mundogeek.net/archivos/2008/03/10/python-programacion-funcional/</link>
		<comments>http://mundogeek.net/archivos/2008/03/10/python-programacion-funcional/#comments</comments>
		<pubDate>Mon, 10 Mar 2008 10:00:37 +0000</pubDate>
		<dc:creator>Zootropo</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[decoradores]]></category>
		<category><![CDATA[funcional]]></category>
		<category><![CDATA[funciones]]></category>
		<category><![CDATA[generadores]]></category>
		<category><![CDATA[lambda]]></category>
		<category><![CDATA[programacion]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://mundogeek.net/archivos/2008/03/10/python-programacion-funcional/</guid>
		<description><![CDATA[La programación funcional es un paradigma en el que la programación se basa casi en su totalidad en funciones, entendiendo el concepto de función según su definición matemática, y no como los simples subprogramas de los lenguajes imperativos que hemos visto hasta ahora. En los lenguajes funcionales puros un programa consiste exclusivamente en la aplicación [...]]]></description>
			<content:encoded><![CDATA[<p>La programación funcional es un paradigma en el que la programación se basa casi en su totalidad en funciones, entendiendo el concepto de función según su definición matemática, y no como los simples subprogramas de los lenguajes imperativos que hemos visto hasta ahora.</p>
<p>En los lenguajes funcionales puros un programa consiste exclusivamente en la aplicación de distintas funciones a un valor de entrada para obtener un valor de salida.</p>
<p>Python, sin ser un lenguaje puramente funcional incluye varias características tomadas de los lenguajes funcionales como son las funciones de orden superior o las funciones lambda (funciones anónimas).</p>
<p><span id="more-1406"></span></p>
<h2>Funciones de orden superior</h2>
<p>El concepto de funciones de orden superior se refiere al uso de funciones como si de un valor cualquiera se tratara, posibilitando el pasar funciones como parámetros de otras funciones o devolver funciones como valor de retorno.</p>
<p>Esto es posible porque, como hemos insistido en diversas ocasiones, en Python todo son objetos. Y las funciones no son una excepción.</p>
<p>Veamos un pequeño ejemplo</p>
<pre class="code"><span class="pythonStatement">def</span> <span class="Identifier">saludar</span>(lang):
    <span class="pythonStatement">def</span> <span class="Identifier">saludar_es</span>():
        <span class="pythonStatement">print</span> <span class="Normal">&quot;</span><span class="String">Hola</span><span class="Normal">&quot;</span>

    <span class="pythonStatement">def</span> <span class="Identifier">saludar_en</span>():
        <span class="pythonStatement">print</span> <span class="Normal">&quot;</span><span class="String">Hi</span><span class="Normal">&quot;</span>

    <span class="pythonStatement">def</span> <span class="Identifier">saludar_fr</span>():
        <span class="pythonStatement">print</span> <span class="Normal">&quot;</span><span class="String">Salut</span><span class="Normal">&quot;</span>

    lang_func = {<span class="Normal">&quot;</span><span class="String">es</span><span class="Normal">&quot;</span>: saludar_es,
                 <span class="Normal">&quot;</span><span class="String">en</span><span class="Normal">&quot;</span>: saludar_en,
                 <span class="Normal">&quot;</span><span class="String">fr</span><span class="Normal">&quot;</span>: saludar_fr}
    <span class="pythonStatement">return</span> lang_func[lang]

f = saludar(<span class="Normal">&quot;</span><span class="String">es</span><span class="Normal">&quot;</span>)
f()</pre>
<p>Como podemos observar lo primero que hacemos en nuestro pequeño programa es llamar a la función <code>saludar</code> con un parámetro <code>"es"</code>. En la función saludar se definen varias funciones: <code>saludar_es</code>, <code>saludar_en</code> y <code>saludar_fr</code> y a continuación se crea un diccionario que tiene como claves cadenas de texto que identifican a cada lenguaje, y como valores las funciones. El valor de retorno de la función es una de estas funciones. La función a devolver viene determinada por el valor del parámetro lang que se pasó como argumento de <code>saludar</code>.</p>
<p>Como el valor de retorno de <code>saludar</code> es una función, como hemos visto, esto quiere decir que <code>f</code> es una variable que contiene una función. Podemos entonces llamar a la función a la que se refiere <code>f</code> de la forma en que llamaríamos a cualquier otra función, añadiendo unos paréntesis y, de forma opcional, una serie de parámetros entre los paréntesis.</p>
<p>Esto se podría acortar, ya que no es necesario almacenar la función que nos pasan como valor de retorno en una variable para poder llamarla:</p>
<p class="code">&gt;&gt;&gt; saludar(&#8220;en&#8221;)()<br />
Hi<br />
&gt;&gt;&gt; saludar(&#8220;fr&#8221;)()<br />
Salut</p>
<p>En este caso el primer par de paréntesis indica los parámetros de la función <code>saludar</code>, y el segundo par, los de la función devuelta por <code>saludar</code>.</p>
<h2>Iteraciones de orden superior sobre listas</h2>
<p>Una de las cosas más interesantes que podemos hacer con nuestras funciones de orden superior es pasarlas como argumentos de las funciones map, filter y reduce. Estas funciones nos permiten sustituir los bucles típicos de los lenguajes imperativos mediante construcciones equivalentes.</p>
<p><strong>map(function, sequence[, sequence, ...])</strong></p>
<p>La función map aplica una función a cada elemento de una secuencia y devuelve una lista con el resultado de aplicar la función a cada elemento. Si se pasan como parámetros n secuencias, la función tendrá que aceptar n argumentos. Si alguna de las secuencias es más pequeña que las demás, el valor que le llega a la función <code>function</code> para posiciones mayores que el tamaño de dicha secuencia será None.</p>
<p>A continuación podemos ver un ejemplo en el que se utiliza <code>map</code> para elevar al cuadrado todos los elementos de una lista:</p>
<pre class="code"><span class="pythonStatement">def</span> <span class="Identifier">cuadrado</span>(n):
    <span class="pythonStatement">return</span> n ** 2

l = [1, 2, 3]
l2 = map(cuadrado, l)</pre>
<p><strong>filter(function, sequence)</strong></p>
<p>La funcion filter verifica que los elementos de una secuencia cumplan una determinada condición, devolviendo una secuencia con los elementos que cumplen esa condición. Es decir, para cada elemento de <code>sequence</code> se aplica la función <code>function</code>, si el resultado es True se añade a la lista y en caso contrario se descarta.</p>
<p>A continuación podemos ver un ejemplo en el que se utiliza <code>filter</code> para conservar solo los números que son pares.</p>
<pre class="code"><span class="pythonStatement">def</span> <span class="Identifier">es_par</span>(n):
    <span class="pythonStatement">return</span> (n % 2.0 == 0)

l = [1, 2, 3]
l2 = filter(es_par, l)</pre>
<p><strong>reduce(function, sequence[, initial])</strong></p>
<p>La función reduce aplica una función a pares de elementos de una secuencia hasta dejarla en un solo valor.</p>
<p>A continuación podemos ver un ejemplo en el que se utiliza <code>reduce</code> para sumar todos los elementos de una lista.</p>
<pre class="code"><span class="pythonStatement">def</span> <span class="Identifier">sumar</span>(x, y):
    <span class="pythonStatement">return</span> x + y

l = [1, 2, 3]
l2 = reduce(sumar, l)</pre>
<h2>Funciones lambda</h2>
<p>El operador lambda sirve para crear funciones anónimas en línea. Al ser funciones anónimas, es decir, sin nombre, estas no podrán ser referenciadas más tarde.</p>
<p>Las funciones lambda se construyen mediante el operador lambda, los parámetros de la función separados por comas (atención, SIN paréntesis), dos puntos (:) y el código de la función.</p>
<p>Esta construcción podrían haber sido de utilidad en los ejemplos anteriores para reducir código. El programa que utilizamos para explicar <code>filter</code>, por ejemplo, podría expresarse así:</p>
<pre class="code">l = [1, 2, 3]
l2 = filter(<span class="pythonStatement">lambda</span> n: n % 2.0 == 0, l)</pre>
<p>Comparemoslo con la versión anterior:</p>
<pre class="code"><span class="pythonStatement">def</span> <span class="Identifier">es_par</span>(n):
    <span class="pythonStatement">return</span> (n % 2.0 == 0)

l = [1, 2, 3]
l2 = filter(es_par, l)</pre>
<p>Las funciones lambda están restringidas por la sintaxis a una sola expresión.</p>
<h2>Comprensión de listas</h2>
<p>En Python 3 map y filter se verán sustituidas por las list comprehensions o comprensión de listas, característica tomada del lenguaje de programación funcional Haskell y que está presente en Python desde la versión 2.0.</p>
<p>La comprensión de listas es una construcción que permite crear listas a partir de otras listas. Cada una de estas construcciones consta de una expresión que determina cómo modificar el elemento de la lista original, seguida de una o varias clausulas for y opcionalmente una o varias clausulas if.</p>
<p>Veamos un ejemplo de cómo se podría utilizar la comprensión de listas para elevar al cuadrado todos los elementos de una lista, como hicimos en nuestro ejemplo de <code>map</code>.</p>
<pre class="code">l2 = [n ** 2 <span class="pythonRepeat">for</span> n <span class="pythonOperator">in</span> l]</pre>
<p>Esta expresión se leería como &#8220;para cada n en l haz n ** 2&#8243;. Como vemos tenemos primero la expresión que modifica los valores de la lista original (n ** 2), después el <code>for</code>, el nombre que vamos a utilizar para referirnos al elemento actual de la lista original, el <code>in</code>, y la lista sobre la que se itera.</p>
<p>El ejemplo que utilizamos para la función filter (conservar solo los números que son pares) se podría expresar con comprensión de listas así:</p>
<pre class="code">l2 = [n <span class="pythonRepeat">for</span> n <span class="pythonOperator">in</span> l <span class="pythonConditional">if</span> n % 2.0 == 0]</pre>
<p>Veamos por último un ejemplo de compresión de listas con varias clausulas for:</p>
<pre class="code">l = [0, 1, 2, 3]
m = [<span class="Normal">&quot;</span><span class="String">a</span><span class="Normal">&quot;</span>, <span class="Normal">&quot;</span><span class="String">b</span><span class="Normal">&quot;</span>]
n = [s * v <span class="pythonRepeat">for</span> s <span class="pythonOperator">in</span> m
           <span class="pythonRepeat">for</span> v <span class="pythonOperator">in</span> l
           <span class="pythonConditional">if</span> v &gt; 0]</pre>
<p>Esta construcción sería equivalente a una serie de for-in anidados:</p>
<pre class="code">l = [0, 1, 2, 3]
m = [<span class="Normal">&quot;</span><span class="String">a</span><span class="Normal">&quot;</span>, <span class="Normal">&quot;</span><span class="String">b</span><span class="Normal">&quot;</span>]
n = []

<span class="pythonRepeat">for</span> s <span class="pythonOperator">in</span> m:
    <span class="pythonRepeat">for</span> v <span class="pythonOperator">in</span> l:
        <span class="pythonConditional">if</span> v &gt; 0:
            n.append(s* v)</pre>
<h2>Generadores</h2>
<p>Las expresiones generadoras funcionan de forma muy similar a la comprensión de listas. De hecho su sintaxis es exactamente igual, a excepción de que se utiliza paréntesis en lugar de corchetes:</p>
<pre class="code">l2 = (n ** 2 <span class="pythonRepeat">for</span> n <span class="pythonOperator">in</span> l)</pre>
<p>Sin embargo las expresiones generadoras se diferencian de la comprensión de listas en que no se devuelve una lista, sino un generador.</p>
<p class="code">&gt;&gt;&gt; l2 = [n ** 2 for n in l]<br />
&gt;&gt;&gt; l2<br />
[0, 1, 4, 9]<br />
&gt;&gt;&gt; l2 = (n ** 2 for n in l)<br />
&gt;&gt;&gt; l2<br />
&lt;generator object at 0x00E33210&gt;</p>
<p>Un generador es una clase especial de función que <em>genera</em> valores sobre los que iterar. Para devolver el siguiente valor sobre el que iterar se utiliza la palabra clave <code>yield</code>. Veamos por ejemplo un generador que devuelva números de <code>n</code> a <code>m</code> con un salto <code>s</code>.</p>
<pre class="code"><span class="pythonStatement">def</span> <span class="Identifier">mi_generador</span>(n, m, s):
    <span class="pythonRepeat">while</span>(n &lt;= m):
        <span class="pythonStatement">yield</span> n
        n += s</pre>
<p class="code">&gt;&gt;&gt; x = mi_generador(0, 5, 1)<br />
&gt;&gt;&gt; x<br />
&lt;generator object at 0x00E25710&gt;</p>
<p>El generador se puede utilizar en cualquier lugar donde se necesite un objeto iterable. Por ejemplo en un for-in:</p>
<pre class="code"><span class="pythonRepeat">for</span> n <span class="pythonOperator">in</span> mi_generador(0, 5, 1):
    <span class="pythonStatement">print</span> n</pre>
<p>Como no estamos creando una lista completa en memoria, sino generando un solo valor cada vez que se necesita, en situaciones en las que no sea necesario tener la lista completa el uso de generadores puede suponer una gran diferencia de memoria. En todo caso siempre es posible crear una lista a partir de un generador mediante la función list:</p>
<pre class="code">lista = list(mi_generador)</pre>
<h2>Decoradores</h2>
<p>Un decorador no es es mas que una función que recibe una función como parámetro y devuelve otra función como resultado. Por ejemplo podríamos querer añadir la funcionalidad de que se imprimiera el nombre de la función llamada por motivos de depuración:</p>
<pre class="code"><span class="pythonStatement">def</span> <span class="Identifier">mi_decorador</span>(funcion):
    <span class="pythonStatement">def</span> <span class="Identifier">nueva</span>(*args):
        <span class="pythonStatement">print</span> <span class="Normal">&quot;</span><span class="String">Llamada a la funcion</span><span class="Normal">&quot;</span>, funcion.__name__
        retorno = funcion(*args)
        <span class="pythonStatement">return</span> retorno
    <span class="pythonStatement">return</span> nueva</pre>
<p>Como vemos el código de la función mi_decorador no hace más que crear una nueva función y devolverla. Esta nueva función imprime el nombre de la función a la que &#8220;decoramos&#8221;, ejecuta el código de dicha función, y devuelve su valor de retorno. Es decir, que si llamáramos a la función <code>nueva</code> que nos devuelve <code>mi_decorador</code>, el resultado sería el mismo que el de llamar directamente a la función que le pasamos como parámetro, exceptuando el que se imprimirá además el nombre de la función.</p>
<p>Supongamos como ejemplo una función <code>imp</code> que no hace otra cosa que mostrar en pantalla la cadena pasada como parámetro.</p>
<p class="code">&gt;&gt;&gt; imp(&#8220;hola&#8221;)<br />
hola<br />
&gt;&gt;&gt; mi_decorador(imp)(&#8220;hola&#8221;)<br />
Llamada a la función imp<br />
hola</p>
<p>Ahora bien, la sintaxis para llamar a la función que nos devuelve <code>mi_decorador</code> no es muy clara, aunque si lo estudiamos detenidamente veremos que no tiene mayor complicación. Primero se llama a la función que decora con la función a decorar: <code>mi_decorador(imp)</code>; y una vez obtenida la función ya decorada se la puede llamar pasando el mismo parámetro que se pasó anteriormente: <code>mi_decorador(imp)("hola")</code></p>
<p>Esto se podría expresar más claramente precediendo la definición de la función que queremos decorar con el signo @ seguido del nombre de la función decoradora:</p>
<pre class="code"><span class="Define">@</span><span class="Identifier">mi_decorador</span>
<span class="pythonStatement">def</span> <span class="Identifier">imp</span>(s):
    <span class="pythonStatement">print</span> s</pre>
<p>De esta forma cada vez que se llame a <code>imp</code> se estará llamando realmente a la versión decorada. Python incorpora esta sintaxis desde la versión 2.4 en adelante.</p>
<p>Si quisiéramos aplicar más de un decorador bastaría añadir una nueva línea con el nuevo decorador.</p>
<pre class="code"><span class="Define">@</span><span class="Identifier">otro_decorador</span>
<span class="Define">@</span><span class="Identifier">mi_decorador</span>
<span class="pythonStatement">def</span> <span class="Identifier">imp</span>(s):
    <span class="pythonStatement">print</span> s</pre>
<p>Es importante advertir que los decoradores se ejecutarán de abajo a arriba. Es decir, en este ejemplo primero se ejecutaría <code>mi_decorador</code> y después <code>otro_decorador</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://mundogeek.net/archivos/2008/03/10/python-programacion-funcional/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
	</channel>
</rss>

