Sobre decoradores en Python

Hola a todos!


Se preparó la traducción del artículo para los estudiantes del curso "Desarrollador web en Python" . ¿Es interesante desarrollar en esta dirección? Regístrese para el curso del Día de Puertas Abiertas y chatee en vivo con el maestro: transmisión en línea el 23 de julio a las 20:00 hora de Moscú.



Cuando practicaste la programación en Python, debes haberte encontrado con un concepto como decoradores. Son una de las herramientas más elegantes y de uso frecuente en bibliotecas y marcos modernos. Los decoradores son una buena forma de encapsular muchos detalles de implementación, dejando una interfaz simple en la superficie.


Veamos un ejemplo de un simple decorador de inicio de sesión que verifica que un usuario haya iniciado sesión antes de darle la oportunidad de editar publicaciones. Luego, el decorador redirige a la página de inicio de sesión o registro, y luego, con la ayuda de los parámetros establecidos correctamente, regresa a la misma página después de una autenticación exitosa. Para usar esta función, solo necesita escribir @login_required antes de la función de destino.


@login_required def edit_post(post_id): ... 

Es muy fácil trabajar con los decoradores, pero crear decoradores no es una tarea fácil, incluso para programadores experimentados de Python. En este artículo, veremos paso a paso cómo funcionan los decoradores en Python.


Las funciones


Las funciones también se denominan objetos de primera clase en Python. Las funciones son los mismos valores que los números, las listas y las cadenas, como se ve en el siguiente ejemplo.


 >>> def foo(): ... return 1 ... >>> >>> foo() 1 >>> 

Las funciones tienen su propio espacio de nombres, donde buscan nombres de variables en primer lugar cuando ocurren en el cuerpo de una función. Escribamos una función simple para comprender la diferencia entre el alcance global y el local.


 >>> >>> a_string = "This is a global variable" >>> >>> def foo(): ... print(locals()) ... >>> >>> print(globals()) {..., 'a_string': 'This is a global variable'} >>> >>> foo() # 2 {} >>> 

Alcance de la función como variable


La regla de alcance en Python dice que cuando se crea una variable, siempre se crea una nueva variable local, pero el acceso a la variable se determina en el alcance local cuando busca nombres de variables en todas las áreas de coincidencia más cercanas. Esto no significa que no podamos acceder a las variables globales desde nuestra función. Para generar una variable global, cambiamos la función foo de la siguiente manera:


 >>> >>> a_string = "This is a global variable" >>> >>> def foo(): ... print(a_string) #1 ... >>> >>> foo() This is a global variable >>> 

Vida útil variable


No solo las variables viven en el espacio de nombres, sino que también tienen una vida útil, lo cual es importante recordar. Considere un ejemplo que ilustra no solo las reglas de alcance y los problemas que pueden causar, sino también cómo interactúan con las llamadas a funciones y cómo funcionan en Python y otros lenguajes.


 >>> def foo(): ... x = 1 ... >>> foo() >>> >>> print(x) # 1 Traceback (most recent call last): ... NameError: name 'x' is not defined >>> 

Funciones anidadas


Puede crear funciones anidadas en Python, lo que significa que podemos declarar funciones dentro de funciones, y todas las reglas de alcance y vida útil aún se aplican.


 >>> >>> def outer(): ... x = 1 ... def inner(): ... print(x) # 1 ... inner() # 2 ... >>> outer() 1 >>> 

Decoradores


Un cierre que toma una función como parámetro y devuelve una función se llama decorador. Considere un ejemplo de decoradores útiles.


 >>> >>> def outer(some_func): ... def inner(): ... print("before some_func") ... ret = some_func() # 1 ... return ret + 1 ... return inner ... >>> def foo(): ... return 1 ... >>> decorated = outer(foo) # 2 >>> >>> decorated() before some_func 2 >>> 

Una variable decorada es una versión decorada de foo. De hecho, podríamos reemplazar foo con su versión decorada y no aprender la nueva sintaxis simplemente reasignando la variable que contiene nuestra función:


 >>> >>> foo = outer(foo) >>> >>> foo # doctest: +ELLIPSIS <function outer.<locals>.inner at 0x...> >>> 

Ahora tenemos un hermoso decorador para rastrear llamadas a funciones. Los decoradores se pueden usar para trabajar con cualquier lenguaje de programación usando Python. Esta es una herramienta extremadamente útil, cuyo mecanismo de trabajo debe entenderse para aplicarlos correctamente.

Source: https://habr.com/ru/post/460931/


All Articles