La función partial apareció en la biblioteca estándar de Python (módulo functools), a partir de Python 2.5, para implementar el patrón de currying y la aplicación parcial de argumentos a una función. La función partialmethod apareció con Python 3.4 para un uso similar en métodos de clases.
A menudo, en proyectos reales, surge la necesidad de fijar parte de los argumentos en una función para obtener una nueva función con valores "recordados" de algunos argumentos. Esto es conveniente para callbacks, plantillas de paso de argumentos, o para aumentar la legibilidad del código, especialmente en programación funcional y al usar API que esperan un estilo particular de funciones.
La función partial devuelve un nuevo objeto-función, en la que algunos de los argumentos o argumentos clave pasados están "fijados". La función partialmethod implementa el mismo enfoque para los métodos de clases, admitiendo correctamente la mecánica de paso de self/cls.
Ejemplo de código:
from functools import partial, partialmethod def power(base, exponent): return base ** exponent # Fijamos el exponente = 2 square = partial(power, exponent=2) print(square(5)) # 25 class Math: def power(self, base, exponent): return base ** exponent square = partialmethod(power, exponent=2) m = Math() print(m.square(5)) # 25
Características clave:
¿Se puede usar partial para métodos de clase para obtener un equivalente a partialmethod?
No, partial no maneja self/cls correctamente, al aplicarlo a un método de clase no funcionará como se espera: self no se asignará automáticamente.
class C: def m(self, x, y): return x + y wrong = partial(m, y=2) # ¡Incorrecto!
Al llamar c.wrong(5) se producirá un TypeError, porque self no se pasará automáticamente.
¿El objeto creado a través de partial es una función?
Sí, el resultado de partial es un objeto que se comporta como una función, admite llamada, nombre, docstring, etc., pero no es una función normal, es un objeto de la clase partial, que implementa el protocolo call.
from functools import partial f = partial(pow, 2) print(type(f)) # <class 'functools.partial'>
¿Funciona partial con los argumentos por defecto de una función?
Sí, partial puede "sobrescribir" los valores por defecto en la función interna; si se pasan argumentos a partial, tienen prioridad sobre los valores por defecto en la propia función. Sin embargo, es importante no duplicar valores, de lo contrario habrá un error.
El desarrollador aplica partial para un método de clase en lugar de partialmethod:
class MyClass: def f(self, x, y): ... squared = partial(f, y=2) ... obj = MyClass() obj.squared(5) # TypeError: missing 1 required positional argument: 'self'
Pros:
Contras:
En su lugar se aplica partialmethod:
from functools import partialmethod class MyClass: def f(self, x, y): return x + y squared = partialmethod(f, y=2) obj = MyClass() print(obj.squared(5)) # 7
Pros:
Contras: