summaryrefslogtreecommitdiff
path: root/es/04_funciones.md
diff options
context:
space:
mode:
Diffstat (limited to 'es/04_funciones.md')
-rw-r--r--es/04_funciones.md73
1 files changed, 37 insertions, 36 deletions
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:
- <https://en.wikipedia.org/wiki/Deductive_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]: <https://www.python.org/dev/peps/pep-0289/>
+[^pep289]: Los PEP son documentos donde se proponen mejoras para el lenguaje.
+ Puedes leer el contenido completo del PEP en:
+ <https://www.python.org/dev/peps/pep-0289/>
### 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]: <https://en.wikipedia.org/wiki/Switch_statement>
-
### 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.