Funciones anidadas de Python

    ¿Qué es una función anidada?

    Las funciones son uno de los «ciudadanos de primera clase» de Python, lo que significa que las funciones están al mismo nivel que otros objetos de Python como enteros, cadenas, módulos, etc. Se pueden crear y destruir dinámicamente, pasar a otras funciones, devolver como valores, etc.

    Python admite el concepto de «función anidada» o «función interna», que es simplemente una función definida dentro de otra función. En el resto del artículo, usaremos la palabra «función interna» y «función anidada» indistintamente.

    Hay varias razones por las que a uno le gustaría crear una función dentro de otra función. La función interna puede acceder a las variables dentro del ámbito adjunto. En este artículo, exploraremos varios aspectos de las funciones internas en Python.

    Definición de una función interna

    Para definir una función interna en Python, simplemente creamos una función dentro de otra función usando Python def palabra clave. Aquí hay un ejemplo:

    def function1(): # outer function
        print ("Hello from outer function")
        def function2(): # inner function
            print ("Hello from inner function")
        function2()
    
    function1()
    

    Salida

    Hello from outer function
    Hello from inner function
    

    En el ejemplo anterior, function2() ha sido definido por dentro function1(), convirtiéndolo en una función interna. Llamar function2(), primero debemos llamar function1(). los function1() luego continuará y llamará function2() como se ha definido en su interior.

    Es importante mencionar que se debe llamar a la función externa para que se ejecute la función interna. Si no se llama a la función externa, la función interna nunca se ejecutará. Para demostrar esto, modifique el código anterior a lo siguiente y ejecútelo:

    def function1(): # outer function
        print ("Hello from outer function")
        def function2(): # inner function
            print ("Hello from inner function")
        function2()
    

    ¡El código no devolverá nada cuando se ejecute!

    Aquí hay otro ejemplo:

    def num1(x):
       def num2(y):
          return x * y
       return num2
    res = num1(10)
    
    print(res(5))
    

    Salida

    50
    

    El código devuelve la multiplicación de los dos números, es decir, 10 y 5. El ejemplo muestra que una función interna puede acceder a variables accesibles en la función externa.

    Hasta ahora, has visto que es posible que accedamos a las variables de la función externa dentro de la función interna. ¿Qué pasa si intentamos cambiar las variables de la función externa desde dentro de la función interna? Veamos que pasa:

    def function1(): # outer function
        x = 2 # A variable defined within the outer function
        def function2(a): # inner function
           # Let's define a new variable within the inner function
           # rather than changing the value of x of the outer function
            x = 6
            print (a+x)
        print (x) # to display the value of x of the outer function
        function2(3)
    
    function1()
    

    Salida

    2
    9
    

    La salida muestra que es posible para nosotros mostrar el valor de una variable definida dentro de la función externa desde la función interna, pero no cambiarlo. La declaración x = 6 nos ayudó a crear una nueva variable x dentro de la función interna function2() en lugar de cambiar el valor de la variable x definido en la función externa function1().

    En la siguiente sección, discutiremos las razones principales por las que usamos funciones internas en Python.

    ¿Por qué utilizar las funciones internas?

    Encapsulamiento

    Se puede crear una función como función interna para protegerla de todo lo que sucede fuera de la función. En ese caso, la función se ocultará del ámbito global. Aquí hay un ejemplo:

    def outer_function(x):
        # Hidden from the outer code
        def inner_increment(x):
            return x + 2
        y = inner_increment(x)
        print(x, y)
    
    inner_increment(5)
    #outer_function(5)
    

    Salida

    Traceback (most recent call last):
      File "C:/Users/admin/inner.py", line 7, in <module>
        inner_increment(5)
    NameError: name 'inner_increment' is not defined
    

    En el código anterior, estamos intentando llamar al inner_increment() función, pero en su lugar obtuvimos un error.

    Ahora, comente la llamada a inner_increment() y descomentar la llamada a outer_function() Como se muestra abajo:

    def outer_function(x):
        # Hidden from the outer code
        def inner_increment(x):
            return x + 2
        y = inner_increment(x)
        print(x, y)
    
    #inner_increment(5)
    outer_function(5)
    

    Salida

    5 7
    

    El script anterior muestra que la función interna, es decir, inner_increment() está protegido de lo que sucede fuera de él ya que la variable x dentro de inner_increment la función no se ve afectada por el valor pasado al parámetro x de la función exterior. En otras palabras, las variables dentro de la función interna no son accesibles fuera de ella. Existe una gran ventaja con este patrón de diseño. Después de verificar todos los argumentos en la función externa, podemos omitir con seguridad la verificación de errores dentro de la función interna.

    Cierres y funciones de fábrica

    Todos los ejemplos que hemos visto hasta ahora solo contienen funciones ordinarias que se han anidado dentro de otras funciones. Es posible para nosotros escribir tales funciones de otra manera en lugar de anidarlas dentro de otras funciones. No tenemos una razón específica de por qué deberíamos anidarlos.

    Sin embargo, para el caso de cierres, uno debe usar las funciones anidadas.

    Podemos vincular / pasar datos a una función sin pasar necesariamente los datos a la función a través de parámetros. Esto se hace mediante un cierre. Es un objeto de función que puede recordar valores en los ámbitos adjuntos incluso cuando no están disponibles en la memoria. Esto significa que tenemos un cierre cuando una función anidada hace referencia a un valor que está en su ámbito adjunto.

    El propósito de un cierre es hacer que la función interna recuerde el estado de su entorno cuando se llama, incluso si no está en la memoria. Un cierre es causado por una función interna, pero no es la función interna. El cierre funciona cerrando la variable local en la pila, que permanece después de que la creación de la pila ha terminado de ejecutarse.

    Las siguientes son las condiciones que se deben cumplir para crear un cierre en Python:

    • Debe haber una función anidada
    • La función interna tiene que hacer referencia a un valor que se define en el ámbito adjunto
    • La función envolvente tiene que devolver la función anidada

    Considere el siguiente ejemplo:

    def function1(name):
        def function2():
            print('Hello ' + name)
        return function2
    
    func = function1('Nicholas')
    func()
    

    Salida

    Hello Nicholas
    

    El código anterior demuestra que con los cierres, podemos generar e invocar una función desde fuera de su alcance a través del paso de funciones. El alcance de function2() esta solo adentro function1(). Sin embargo, con el uso de cierres, nos fue posible extender este alcance e invocarlo desde fuera de su alcance.

    Las funciones internas nos ayudan a definir funciones de fábrica. Una función de fábrica es una función que crea otro objeto. Por ejemplo:

    def power_generator(num):
    
        # Create the inner function
        def power_n(power):
            return num ** power
    
        return power_n
    
    power_two = power_generator(2)
    power_three = power_generator(3)
    print(power_two(8))
    print(power_three(4))
    

    Salida

    256
    81
    

    En el guión de arriba, del power_n(power) función, hemos creado otros dos objetos, power_two y power_three. Esto hace power_n(power) una función de fábrica ya que genera la power_two y power_three funciones para nosotros usando el parámetro que le pasamos.

    Conclusión

    Una función interna es simplemente una función que se define dentro de otra función. La función interna puede acceder a las variables que se han definido dentro del alcance de la función externa, pero no puede cambiarlas. Hay varias razones por las que es posible que necesitemos crear una función interna. Por ejemplo, una función interna está protegida de lo que sucede fuera de ella. Las funciones internas también son una buena forma de crear cierres en Python.

     

    Etiquetas:

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *