Cómo multiplicar funciones en python?
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 una tecla , es un poco cojo:
>>> sorted(my_list, key=lambda n: square(sub3(n)))
[3, 2, 4, 1, 5, 0, 6, 7, 8, 9]
Esto realmente debería ser sorted(my_list, key=square*sub3)
, porque diablos, function __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 alguna parte..
>>> 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 un Hack
¡clase llamable! Las reglas de alcance son totalmente diferentes en formas que no entiendo completamente, y esto es incluso más feo que el "lameda" sin duda. Quiero emparejar las funciones . ¿Cómo puedo hacer eso?
3 answers
Puedes usar tu clase de hackeo como decorador prácticamente tal como está escrita, aunque probablemente quieras elegir un nombre más apropiado para la clase.
Así:
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 de la siguiente manera:
@Composable
def sub3(n):
return n - 3
@Composable
def square(n):
return n * n
Y componerlos de esta manera:
(square * sub3)(n)
Básicamente es lo mismo que has logrado usando tu clase de hackeo, pero usándolo como decorador.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-13 00:30:44
Python no tiene (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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-12 16:04:56
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 luego:
sorted(my_list, key=Composition(square, sub3))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-12 16:43:53