Funciones anidadas
Funciones anidadas
Antes de comenzar a hablar de las funciones anidadas es importante destacar algunos detalles sobre las funciones, por ejemplo las funciones se pueden asignar a variables, veamos el siguiente ejemplo:
import os
os.system('cls')
def suma(a,b):
return a+b
operacion = suma
print(f'La variable operacion pertenece a la: {type(operacion)}')
print(f'La suma de 10 + 5 es: {operacion(10,5)}')
Resultado:
La variable operacion pertenece a la: <class 'function'>
La suma de 10 + 5 es: 15
Como podemos ver en el código anterior se ha asignado una función llamada suma a la variable operacion, haciendo que la variable suma ahora pertenezca a la clase funcion en Python. Como podemos comprobar invocando a la función TYPE. Esto hace que la variable operacion admita los argumentos que admite la función original asignada, en este caso, a través de los parámetros a y b. De igual manera hemos podido comprobar que al invocar al objeto operacion con los parámetros 10 y 5 efectivamente los suma como fue establecido en la función suma.
Una función también puede ser usada como argumento de otra función. Veamos el siguiente ejemplo:
import os
os.system('cls')
def suma(a,b):
return a+b
def mi_funcion(funcion,texto):
return texto + str(funcion)
print(mi_funcion(suma(3,2),'La suma de 2 y 3 da como resultado: '))
Resultado:
La suma de 2 y 3 da como resultado: 5
Si bien esta es una manera muy poco óptima de realizar la suma de 2 números, el ejempo sirve para ilustrar el concepto del uso de una función como argumento de otra función. En este caso hemos definido dos funciones, la función suma cuyo única tarea es la de sumar los dos argumentos recibidos, a y b, devolviendo dicha suma en la instrucción RETURN, la otra función definida es la función mi_funcion, la cual admite tres argumentos, el primero a través del parámetro llamado funcion y el segundo a través del parámetro llamado texto. La tarea de esta función es concatenar el texto recibido con el valor entero devuelto a través de la función recibida llamada funcion, que como ya se dijo anteriormente devuelve la suma de 2 valores. La instrucción final es un método print que invoca a la función mi_funcion la cual a su vez invoca a la función suma con los parámetros 3 y 2, y como segundo argumento de la función mi_funcion se encuentra la cadena de texto 'La suma de 2 y 3 da como resultado: '. De esta forma se ha invocado a una función desde otra que la recibe como argumento en uno de sus parámetros.
Ahora bien, volviendo al tema de las funciones anidadas, basta con mencionar que en Python a diferencia de otros lenguajes de programación, se pueden anidar funciones dentro de otras. Para ello basta con declarar la función con la palabra reservada DEF, dentro de otra función definida con la misma palabra reservada DEF. Veamos el siguiente ejemplo:
import os
os.system('cls')
def funcion_externa():
def funcion_interna():
pass
print('Se ha definido una función anidada')
Resultado:
Se ha definido una función anidada
Como podemos comprobar en el código anterior, se ha definido una función llamada funcion_interna() anidada dentro de otra función llamada funcion_externa(). El intérprete de Python admite esta clase de anidaciones de funciones sin problemas. Ahora bien el ámbito o alcance de las variables definidas dentro de las funciones ya es otro tema
Alcance de las variables en funciones anidadas
Ya se ha mencionado ampliamente con ejemplos el alcance y ámbito de las variables dentro de las funciones, en el caso de las funciones anidadas pasa exactamente lo mismo, la función contenedora se consideraria el ámbito global de las funciones contenidas mientras que las funciones contenidas serían el ámbito local de las variables declaradas dentro de cada una de ellas. Veamos el siguiente ejemplo:
import os
os.system('cls')
def funcion_externa():
def funcion_interna():
sVariableInterna='Cadena Interna'
print(sVariableExterna)
print(sVariableInterna)
return
sVariableExterna='Cadena Externa'
funcion_interna()
return
funcion_externa()
Resultado:
Cadena Externa
Cadena Interna
Como podemos deducir del código anterior desde la función interna se ha podido acceder a las variables declaradas en su ámbito y en el ámbito externo a ella, sin embargo en el caso de querer acceder a la variable interna desde la función externa no va a ser posible ya que el intérprete de Python devolverá un error. Veamos el siguiente ejemplo:
import os
os.system('cls')
def funcion_externa():
sVariable_Externa='Cadena externa'
def funcion_interna():
sVariable_Interna='Cadena Interna'
return
print(sVariable_Interna)
funcion_interna()
return
funcion_externa()
Resultado:
Traceback (most recent call last):
File "e:\Documentos\Desarrollos\Python\Curso-Python\10 Funciones definidas por el usuario.py", line
231, in <module>
funcion_externa()
File "e:\Documentos\Desarrollos\Python\Curso-Python\10 Funciones definidas por el usuario.py", line
228, in funcion_externa
print(sVariable_Interna)
NameError: name 'sVariable_Interna' is not defined. Did you mean: 'sVariable_Externa'?
Como podemos ver el intérprete de Python arrojó un error y no pudo ejecutar el código, ya que la variable llamada sVariable_Interna no esta definida en el ámbito desde donde se está intentando acceder, es decir un nivel superior al que posee dicha variable.
Podemos concluir que el tiempo de vida de las variables que se encuentran declaradas en un nivel superior es mayor al tiempo de vida de las que se encuentran en niveles inferiores ya que las variables declaradas en ámbitos superiores pueden ser usadas en ámbitos inferiores pero no al revés.
La palabra reservada NONLOCAL.
Consideremos el siguiente ejemplo:
import os
os.system('cls')
def funcion_externa():
sVariable_Externa='Cadena externa'
def funcion_interna():
sVariable_Interna='Cadena Interna'
sVariable_Externa='Cadena modificada dentro de la función interna'
print(sVariable_Externa)
return
print(f'Valor de la variable antes de la modificación: {sVariable_Externa}')
funcion_interna()
print(f'Valor de la variable luego de la modificación: {sVariable_Externa}')
return
funcion_externa()
Resultado:
Valor de la variable antes de la modificación: Cadena externa
Cadena modificada dentro de la función interna
Valor de la variable luego de la modificación: Cadena externa
Como podemos ver Python parece haber olvidado la modificación que se le hizo a la variable sVariable_Externa dentro de la función interna ya que al mostrar el contenido de la variable al salir de dicha función se mantiene el valor original establecido en la función de nivel superior. Esto se debe a que la variable sVariable_Externa de la función interna no es la misma que la del mismo nombre declarada en la función externa. Para poder utilizar la misma variable de un nivel superior dentro de una función anidada es necesario usar la palabra reservada NONLOCAL. Veamos el siguiente ejemplo:
import os
os.system('cls')
def funcion_externa():
sVariable_Externa='Cadena externa'
def funcion_interna():
nonlocal sVariable_Externa
sVariable_Interna='Cadena Interna'
sVariable_Externa='Cadena modificada dentro de la función interna'
print(sVariable_Externa)
return
print(f'Valor de la variable antes de la modificación: {sVariable_Externa}')
funcion_interna()
print(f'Valor de la variable luego de la modificación: {sVariable_Externa}')
return
funcion_externa()
Resultado:
Valor de la variable antes de la modificación: Cadena externa
Cadena modificada dentro de la función interna
Valor de la variable luego de la modificación: Cadena modificada dentro de la función interna
Como podemos comprobar Python ahora si hace referencia a la variable sVariable_Externa en la modificación que se hace dentro de la función anidada, ya que al imprimir el valor desde fuera de dicha función mantiene el cambio que se le hizo.
Comentarios
Publicar un comentario