resueltos - ¿Cómo multiplicar funciones en python?
lista de funciones de python (3)
Puede usar su clase de hackeo como decorador, tal como está escrito, aunque es probable que desee elegir un nombre más apropiado para la clase.
Me gusta esto:
class Composable(object):
def __init__(self, function):
self.function = function
def __call__(self, *args, **kwargs):
return self.function(*args, **kwargs)
def __mul__(self, other):
@Composable
def composed(*args, **kwargs):
return self.function(other(*args, **kwargs))
return composed
def __rmul__(self, other):
@Composable
def composed(*args, **kwargs):
return other(self.function(*args, **kwargs))
return composed
Luego puedes decorar tus funciones así:
@Composable
def sub3(n):
return n - 3
@Composable
def square(n):
return n * n
Y componerlos así:
(square * sub3)(n)
Básicamente es lo mismo que has logrado usando tu clase de hack, pero usándolo como decorador.
def sub3(n):
return n - 3
def square(n):
return n * n
Es muy fácil componer funciones en python:
>>> my_list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [square(sub3(n)) for n in my_list]
[9, 4, 1, 0, 1, 4, 9, 16, 25, 36]
Desafortunadamente, cuando se quiere usar la composición como clave , es un poco cojo:
>>> sorted(my_list, key=lambda n: square(sub3(n)))
[3, 2, 4, 1, 5, 0, 6, 7, 8, 9]
Esto debería ser sorted(my_list, key=square*sub3)
, porque diablos, la función __mul__
no se usa para nada más de todos modos:
>>> square * sub3
TypeError: unsupported operand type(s) for *: ''function'' and ''function''
Bueno, vamos a definirlo entonces!
>>> type(sub3).__mul__ = ''something''
TypeError: can''t set attributes of built-in/extension type ''function''
D''oh!
>>> class CoolerFunction(types.FunctionType):
... pass
...
TypeError: Error when calling the metaclass bases
type ''function'' is not an acceptable base type
D''oh!
class Hack(object):
def __init__(self, function):
self.function = function
def __call__(self, *args, **kwargs):
return self.function(*args, **kwargs)
def __mul__(self, other):
def hack(*args, **kwargs):
return self.function(other(*args, **kwargs))
return Hack(hack)
Hey, ahora estamos llegando a algún lugar ..
>>> square = Hack(square)
>>> sub3 = Hack(sub3)
>>> [square(sub3(n)) for n in my_list]
[9, 4, 1, 0, 1, 4, 9, 16, 25, 36]
>>> [(square*sub3)(n) for n in my_list]
[9, 4, 1, 0, 1, 4, 9, 16, 25, 36]
>>> sorted(my_list, key=square*sub3)
[3, 2, 4, 1, 5, 0, 6, 7, 8, 9]
¡Pero no quiero una clase de Hack
callable! Las reglas de alcance son totalmente diferentes en formas que no entiendo completamente, y esto es incluso más feo que el "lameda" posiblemente. Quiero monkeypatch las funciones . ¿Cómo puedo hacer eso?
Python no (y probablemente nunca) tendrá soporte para la composición de funciones, ya sea a nivel sintáctico o como una función de biblioteca estándar. Hay varios módulos de terceros (como functional ) que proporcionan una función de orden superior que implementa la composición de la función.
Tal vez algo como esto:
class Composition(object):
def __init__(self, *args):
self.functions = args
def __call__(self, arg):
result = arg
for f in reversed(self.functions):
result = f(result)
return result
Y entonces:
sorted(my_list, key=Composition(square, sub3))