python python-3.x python-decorators function-composition

python - title graph matplotlib



Como hacer un compositor funcional. (3)

Estoy tratando de hacer una función que redondea otras funciones para mi título universitario. Por ejemplo, me gustaría llamar a round_sqrt = round(sqrt) y cuando llamo a round_sqrt(5) tiene que mostrarme 2 lugar de 2.23606797749979 . Lo que estoy tratando es esto:

def rounding(funct): return round(funct)

pero esto no funciona.

EDITAR: La función debe tener un solo parámetro. Por ejemplo, el inicio de la función debe ser

def rounding(func):

así que en esta función la función funct necesita ser redondeada. así que cuando llamo al rounding(abs)(3.2) me muestra 3 .


Deberías revisar los cierres:

def rounder(func): def inner(*args, **kwargs): return round(func(*args, **kwargs)) return inner

Luego puedes decorar funciones usando el caracter @ :

@rounder def adder(x, y): return x + y print(adder(1.1, 2.2))

salidas 3

Suplementario:

  1. Puede utilizar functools.wraps en su cierre para no perder información (por ejemplo, docstring, nombre de la función) sobre la función original.
  2. Hay un montón de recursos para aprender sobre cierres (por ejemplo, 1 , 2 ) y decoradores (por ejemplo, 1 , 2 ) que puede encontrar al buscar en Google esos términos.

La composición de funciones no se admite de forma nativa en Python. Puedes usar un decorador según la solución de @ Alex . Puede definir una nueva función explícitamente según la solución de @chepner .

O puede utilizar una biblioteca de terceros. Por ejemplo, a través de toolz.compose :

from toolz import compose def adder(x, y): return x + y round_adder = compose(round, adder) round_adder(1.1, 2.2) # 3


Para su ejemplo específico, puede escribir

def round_sqrt(x): return round(sqrt(x))

La respuesta de Alex generaliza esto; Él define una función que crea round_sqrt para ti. Si la función ya está definida, simplemente la pasa como un argumento para rounder :

round_sqrt = rounder(sqrt)

Por supuesto, no es necesario definir round_sqrt si no lo desea. rounder(sqrt)(3.2) puede llamarse directamente, aunque es mucho más eficiente asegurar el valor de retorno de rounder si espera usarlo varias veces, en lugar de redefinirlo cada vez.

De lo contrario, la sintaxis del decorador es corta para (usando el ejemplo de Alex)

def adder(x, y): return x + y adder = rounder(adder)

Como dije en mi comentario, este es un ejemplo de implementación de la composición. Matemáticamente, la composición es simple, porque las funciones matemáticas siempre toman un solo argumento y devuelven un solo argumento. Como tal, la composición de dos funciones f y g siempre podría definirse simplemente como

def compose(f, g): def h(x): # The name doesn''t matter return f(g(x)) return h

Entonces

round_sqrt = compose(round, sqrt)

(Ignorando todo tipo de preocupaciones prácticas en torno a la implementación, Python podría, en teoría, proporcionar un operador Unicode para las funciones: round_sqrt = round ∘ sort . Explicar por qué esto no sucederá va más allá del alcance de esta respuesta).

En Python, sin embargo, las funciones son mucho más complicadas. Pueden tomar múltiples argumentos, pueden aceptar un número arbitrario de argumentos y argumentos de palabra clave arbitrarios, y mientras que cada uno retorna técnicamente un valor único, ese valor puede ser una tupla que se considera como valores múltiples o dict . Como resultado, puede haber muchas maneras en las que podría esperar pasar el valor de retorno de g a una función f , más de lo que puede acomodarse fácilmente en una función de compose simple.