El módulo functools en Python trata con funciones de orden superior , es decir, funciones que operan (tomando como argumentos) o que devuelven funciones y otros objetos a los que se puede llamar. El módulo functools proporciona una amplia gama de métodos como cached_property(func), cmp_to_key(func), lru_cache(func), wraps(func), etc. Cabe señalar que estos métodos toman funciones como argumentos. En este artículo, discutiremos el propósito y la aplicación del método update_wrapper() provisto por el módulo functools. Este método se usa para actualizar los metadatos de la función contenedora para reflejar los de la función envuelta, lo que permite una mejor legibilidad y reutilización del código. El método update_wrapper() toma los siguientes argumentos:
Sintaxis: @functools.update_wrapper(wrapper, envuelto, asignado = WRAPPER_ASSIGNMENTS, actualizado = WRAPPER_UPDATES)
Parámetros:
- contenedor: una función contenedora.
- envuelto: la función que se está envolviendo o la función envuelta.
- asignado: atributos de la función envuelta que se asignan a los atributos coincidentes de la función de envoltura como una tupla (argumento opcional).
- actualizado: atributos de la función contenedora que se actualizan con respecto a los atributos de la función original como una tupla (argumento opcional).
Para comprender mejor este método, observemos algunos casos de uso de decoradores y parciales en Python.
Ejemplo 1:
Python3
# Defining the decorator def hi(func): def wrapper(): "Hi has taken over Hello Documentation" print("Hi geeks") func() return wrapper @hi def hello(): "this is the documentation of Hello Function" print("Hey Geeks") # Driver Code print(hello.__name__) print(hello.__doc__) help(hello)
Producción:
wrapper Hi has taken over Hello Documentation Help on function wrapper in module __main__: wrapper() Hi has taken over Hello Documentation
En el ejemplo anterior, cuando usamos la función decoradora hola y usamos su envoltorio para envolver hola , las constantes de nivel de módulo de la función hola , como __name__ , __doc__ , etc., se reemplazan por las del envoltorio en la función hola . La misma situación surge al usar parciales del módulo functools. Veamos un ejemplo :
Ejemplo 2:
Python3
import functools def divide(a, b): "Original Documentation of Divide" return a / b half = functools.partial(divide, b = 2) oneThird = functools.partial(divide, b = 3) try: print(half.__name__) except AttributeError: print('No Name') print(half.__doc__)
Producción:
Sin nombre parcial (función, * argumentos, ** palabras clave): nueva función con aplicación parcial de los argumentos y palabras clave proporcionados.
En el ejemplo anterior, half y oneThird no tienen __name__ (arroja un AttributeError cuando se hace referencia) ya que se crearon a través de parciales. Como su documentación, heredan la documentación del método parcial. Los escenarios anteriores son inherentemente problemáticos porque las constantes de nivel de módulo cumplen propósitos importantes para identificar, administrar y recuperar contenido. Los metadatos son extremadamente importantes por estas razones, así como para rastrear el uso del contenido. Por lo tanto, si uno está tratando de crear una API o bibliotecas, no será fácil de usar porque la ayuda (función) no devolverá información significativa sobre cómo usar sus métodos. La ayuda (función)devolvería la documentación de la función contenedora, lo que sería confuso para el usuario. Este problema se puede resolver fácilmente con @functools.update_wrapper(). Consideremos el primer ejemplo. Podemos usar update_wrapper() de la siguiente manera:
Ejemplo 1:
Python3
# Python program to demonstrate # update)wrapper() method import functools as ft # Defining the decorator def hi(func): def wrapper(): "Hi has taken over Hello Documentation" print("Hi geeks") func() # Note The following Steps Clearly print("UPDATED WRAPPER DATA") print(f'WRAPPER ASSIGNMENTS : {ft.WRAPPER_ASSIGNMENTS}') print(f'UPDATES : {ft.WRAPPER_UPDATES}') # Updating Metadata of wrapper # using update_wrapper ft.update_wrapper(wrapper, func) return wrapper @hi def hello(): "this is the documentation of Hello Function" print("Hey Geeks") print(hello.__name__) print(hello.__doc__) help(hello)
Producción:
ASIGNACIONES ACTUALIZADAS DEL CONTENEDOR DE DATOS DEL ENVOLTORIO: (‘__module__’, ‘__name__’, ‘__qualname__’, ‘__doc__’, ‘__annotations__’) ACTUALIZACIONES: (‘__dict__’, ) hola, esta es la documentación de Ayuda de la función Hello en la función hola en el módulo __main__ : hola() esta es la documentación de la Función Hola
Al usar update_wrapper() vemos que la función hola conserva sus metadatos originales. De manera similar, examinemos el segundo ejemplo, pero esta vez usaremos update_wrapper()
Python3
# Python program to demonstrate # update)wrapper() method import functools def divide(a, b): "Original Documentation of Divide" return a / b half = functools.partial(divide, b = 2) oneThird = functools.partial(divide, b = 3) print("UPDATED WRAPPER DATA") print(f'WRAPPER ASSIGNMENTS : {functools.WRAPPER_ASSIGNMENTS}') print(f'UPDATES : {functools.WRAPPER_UPDATES}') # Updating Metadata of wrapper # using update_wrapper ft.update_wrapper(half, divide) try: print(half.__name__) except AttributeError: print('No Name') print(half.__doc__) help(half) help(oneThird)
Producción:
DATOS DEL CONTENEDOR ACTUALIZADO ASIGNACIONES DEL CONTENEDOR: (‘__module__’, ‘__name__’, ‘__qualname__’, ‘__doc__’, ‘__annotations__’) ACTUALIZACIONES: (‘__dict__’,) dividir Documentación original de Divide Ayuda sobre parcial en módulo __main__ objeto: dividir = clase parcial (incrustaciones.objeto) | parcial(función, *args, **palabras clave) – nueva función con aplicación parcial | de los argumentos y palabras clave dados. | | Métodos definidos aquí: | | __call__(self, /, *args, **kwargs) | Llámese a sí mismo como una función. | | __delattr__(yo, nombre, /) | Implementar delattr(self, nombre). | | __getattribute__(yo, nombre, /) | Retorna getattr(self, nombre). | | __nuevo__(*args, **kwargs) de builtins.type | Crear y devolver un nuevo objeto. Consulte la ayuda (tipo) para obtener una firma precisa. | | __reducir__(…) | ayudante para encurtir | | __repr__(uno mismo, /) | Devuelve repr(auto). | | __setattr__(yo, nombre, valor, /) | Implementar setattr(self, nombre, valor). | | __establecerestado__(…) | | ———————————————————————- | Descriptores de datos definidos aquí: | | __dict__ | | argumentos | tupla de argumentos a futuras llamadas parciales | | función | objeto de función para usar en futuras llamadas parciales | | palabras clave | diccionario de argumentos de palabras clave para futuras llamadas parciales Ayuda sobre objeto parcial: clase parcial(construido.objeto) | parcial(función, *args, **palabras clave) – nueva función con aplicación parcial | de los argumentos y palabras clave dados. | | Métodos definidos aquí: | | __call__(self, /, *args, **kwargs) | Llámese a sí mismo como una función. | | __delattr__(yo, nombre, /) | Implemente delattr(self, nombre). | | __getattribute__(yo, nombre, /) | Retorna getattr(self, nombre). | | __nuevo__(*args, **kwargs) de builtins.type | Crear y devolver un nuevo objeto. Consulte la ayuda (tipo) para obtener una firma precisa. | | __reducir__(…) | ayudante para encurtir | | __repr__(uno mismo, /) | Devuelve repr(auto). | | __setattr__(yo, nombre, valor, /) | Implementar setattr(self, nombre, valor). | | __establecerestado__(…) | | ———————————————————————- | Descriptores de datos definidos aquí: | | __dict__ | | argumentos | tupla de argumentos a futuras llamadas parciales | | función | objeto de función para usar en futuras llamadas parciales | | palabras clave | diccionario de argumentos de palabras clave para futuras llamadas parciales
En este ejemplo, vemos que half hereda las constantes básicas de nivel de módulo de la función divide. Cuando usamos ayuda (mitad), vemos que se deriva parcialmente de la división. Vale la pena señalar que ese no es el caso de oneThird, ya que help(oneThird) no nos dice la función principal. Por lo tanto, a través de las ilustraciones anteriores, podemos comprender los casos de uso del método update_wrapper(…) proporcionado en el módulo functools. Para preservar los metadatos de una función para su uso posterior, update_wrapper(…) es una herramienta poderosa que se puede usar sin mucha molestia. El método, por lo tanto, resulta extremadamente útil en casos de decoradores y parciales .
Publicación traducida automáticamente
Artículo escrito por tirtharajsengupta y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA