From c3a0a74c059ac7790008e7325567317435d0c7f8 Mon Sep 17 00:00:00 2001 From: Ekaitz Zarraga Date: Wed, 22 Jul 2020 14:20:07 +0200 Subject: Corrections in first chapters --- es/04_funciones.md | 73 +++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 36 deletions(-) (limited to 'es/04_funciones.md') diff --git a/es/04_funciones.md b/es/04_funciones.md index 618ccd6..2fd3c73 100644 --- a/es/04_funciones.md +++ b/es/04_funciones.md @@ -123,9 +123,10 @@ La sintaxis de una función lambda te la enseño con un ejemplo: 3 ``` -En el ejemplo primero se muestra la declaración de una función y después -colocando los paréntesis de precedencia y después de llamada a función se -construye una función a la izquierda y se ejecuta con los valores `1` y `2`. +En el primer ejemplo se muestra la declaración de una función lambda. En el +segundo, colocando los paréntesis de precedencia y después de llamada a +función, se construye una función lambda y después se ejecuta con los valores +`1` y `2`. Es fácil de entender la sintaxis de la función lambda, básicamente es una función reducida de sólo una sentencia con un `return` implícito. @@ -160,9 +161,7 @@ Las funciones lambda se usan un montón como *closure*, un concepto donde el *scope* se trabaja más allá de lo que hemos visto. Sigamos visitando el *scope*, para entender sus usos más en detalle. -[^lambda]: Toman su nombre del Lambda - Calculus: - +[^lambda]: Toman su nombre del *Lambda Calculus*. ## Scope avanzado @@ -189,11 +188,13 @@ pero sí al revés. Los casos son los siguientes: - Los módulos. Ver capítulo correspondiente - Las clases. Ver capítulo de Programación Orientada a Objetos. - Las funciones, incluidas las funciones anónimas o lambda. -- Las expresiones generadoras[^generator-expression], que normalmente se - encuentran en las *list-comprehension* que ya se han tratado en el capítulo - previo. +- Las expresiones generadoras definidas en el PEP-289[^pep289], que normalmente + se encuentran en las *list-comprehension* que ya se han tratado en el + capítulo previo. -[^generator-expression]: +[^pep289]: Los PEP son documentos donde se proponen mejoras para el lenguaje. + Puedes leer el contenido completo del PEP en: + ### Scope léxico, Closures @@ -212,9 +213,9 @@ def create_incrementer_function(increment): return incrementer increment10 = create_incrementer_function(10) -increment10(10) # Returns 20 +increment10(10) # 20 increment1 = create_incrementer_function(1) -increment1(10) # Returns 11 +increment1(10) # 11 ``` En este ejemplo hemos creado una función que construye funciones que sirven para incrementar valores. @@ -269,7 +270,7 @@ A nivel práctico, las *closures* son útiles para muchas labores que iremos desgranando de forma accidental. Si tienes claro el concepto te darás cuenta dónde aparecen en los futuros ejemplos. -### `global` y `nonlocal` +### Global y No-local Hemos hablado de qué sentencias crean nuevos contextos, pero no hemos hablado de qué pasa si esos nuevos contextos crean referencias cuyo nombre es idéntico @@ -345,11 +346,10 @@ referencias, ya que se sabe a qué contexto debe afectar: al global. Sin embargo, `nonlocal` necesita que la referencia a la que se pretende acceder esté creada, ya que no es posible saber a qué contexto se pretende acceder. -Las sentencias `global` y `nonlocal` son tramposas, ya que son capaces de -alterar el comportamiento del *scope léxico* y convertirlo en *scope dinámico* -en casos extraños. El *scope dinámico* es el caso opuesto al léxico, en el que -las funciones acceden a valores definidos en el contexto donde se ejecutan, no -donde se crean. +Las sentencias `global` y `nonlocal` son tramposas, ya que dificultan la +comprensión del programa. La mejor recomendación que puede hacerse es tratar de +evitarlas. Usarlas en exceso es, en general, un indicador de un mal diseño de +programa. ## Argumentos de entrada y llamadas @@ -388,9 +388,9 @@ TypeError: 'int' object is not callable #### Caso de estudio: Switch Case Si quieres ver un ejemplo avanzado de esto, te propongo la creación de la -estructura *switch-case* [^switch-case], que puede encontrarse en otros -lenguajes, pero que en lugar de usar una estructura basada en un *if* con -múltiples *elif* uses un diccionario de funciones. +estructura *switch-case*, que puede encontrarse en otros lenguajes, pero que en +lugar de usar una estructura basada en un *if* con múltiples *elif* uses un +diccionario de funciones. Las funciones son valores, por lo que pueden ocupar un diccionario como cualquier otro valor. Construyendo un diccionario en cuyas claves se encuentran @@ -425,8 +425,6 @@ except KeyError: ``` -[^switch-case]: - ### Positional vs Keyword Arguments Las funciones tienen dos tipos de argumentos de entrada, aunque sólo hayamos @@ -435,9 +433,11 @@ mostrado uno de ellos de momento. El que ya conoces se denomina *positional argument* y se refiere a que son argumentos que se definen en función de su posición. Los argumentos posicionales deben ser situados siempre en el mismo orden, si no, los -resultados de la función serán distintos. Las referencias `source` y `target` -toman el primer argumento y el segundo respectivamente. Darles la vuelta -resulta en el resultado opuesto al que se pretendía. +resultados de la función serán distintos. + +Observa el siguiente ejemplo. Las referencias `source` y `target` toman el +primer argumento y el segundo respectivamente. Darles la vuelta resulta en el +resultado opuesto al que se pretendía. ``` python def move_file ( source, target ): @@ -459,7 +459,7 @@ argumentos con nombre. No se han utilizado valores por defecto especiales, pero pueden usarse otros. ``` python -def move_file( source=None, target=None): +def move_file(source=None, target=None): "Mueve archivo de `source` a `target" pass @@ -479,7 +479,7 @@ También es posible declarar funciones que acepten cualquier cantidad de argumentos de un tipo u otro. Ésta es la sintaxis: ``` python -def argument_catcher( *args, **kwargs ) +def argument_catcher( *args, **kwargs ): "Función ejecutable con cualquier número de argumentos de entrada, tanto posicionales como con nombre." print( args ) @@ -497,7 +497,7 @@ se capturan en una tupla y los argumentos con nombre en un diccionario. Este tipo de funciones multiargumento se utilizan mucho en los *decorators*, caso que estudiaremos al final de este capítulo. -#### Peligro: Mutable Defaults +#### Peligro: mutable defaults Existe un caso en el que tienes que tener mucho cuidado. Los valores por defecto en los argumentos con nombre se memorizan de una ejecución de la @@ -527,6 +527,9 @@ que es en la sentencia `def` donde aparecen. ## Decorators +> TODO: CAMBIAR EL EJEMPLO POR UNA DE CONTEO DE TIEMPO +> Así se verá la aplicación de los argumentos generales. + Los *decorators* son un concepto que, a pesar de ser bastante concreto, nos permite descubrir todo el potencial de lo que se acaba de tratar en este apartado. Sirven para dotar a las funciones de características adicionales. @@ -634,17 +637,15 @@ en cualquier lugar, lo que te abre la puerta a querer declarar funciones sencillas sin nombre, que se conocen como funciones *lambda*. Una vez has aclarado que las funciones son ciudadanos de primera clase -(*first-class citizens*) ya estabas preparado para afrontar la realidad del -*scope* donde has tratado los contextos y cómo funcionan definiendo el concepto -del *scope léxico* que, colateralmente, te ha enseñado lo que es una *closure*, -un método para implementarlo. Pero también has tenido ocasión de aprender que -en python es posible crear casos de *scope dinámico* mediante las sentencias -`global` y `nonlocal`, que pueden ser útiles, pero es mejor no abusar de ellas. +(*first-class citizens*) ya era momento de afrontar la realidad del *scope* +donde has tratado los contextos y cómo funcionan definiendo el concepto del +*scope léxico* que, colateralmente, te ha enseñado lo que es una *closure*, un +método para implementarlo. Pero no había quedado claro en su momento cómo funcionaban los argumentos de entrada y las llamadas a las funciones, así que has tenido ocasión de ver por primera vez lo que es un *callable* en python, aunque se te ha prometido -analizarlo en el futuro. Lo que sí que has tenido ocasión de tratar son los +analizarlo en el futuro. Lo que sí que has tratado en profundidad son los argumentos *positional* y *keyword*, y cómo se utilizan en todas sus posibles formas. -- cgit v1.2.3