保留功能实现的顺序

时间:2012-04-06 18:16:19

标签: python function functional-programming composition

所以我有一个数值,可以应用这两个函数。

假设我有一个号码8。

我想取它的正方形然后是它的日志或首先是日志然后是它的正方形。

所以我的功能看起来像这样

def transform(value, transformation_list):
  # value is int, transformation_list = ["log",square"] or ["square","log"]
 # square function and log function
 return transformed value

现在,如果转换列表的第一个参数是“square”而第二个参数是“log”, 然后它应该首先执行square然后记录

但是如果该列表中的第一个函数是“log”而第二个是“square”,那么它应该实现第一个log然后是square。

我不想要if:else有点像因为我会添加更多变换会变得丑陋 我该如何设计呢。

2 个答案:

答案 0 :(得分:2)

以下内容应该有效:

import math

func_dict = {'square': lambda x: x**2,
             'cube': lambda x: x**3,
             'log': math.log}

def transform(value, transformation_list):
    for func_name in transformation_list:
        value = func_dict[func_name](value)
    return value

例如:

>>> transform(math.e, ['cube', 'log', 'square'])
9.0

答案 1 :(得分:2)

使用此recipe进行函数组合(或者使用functional模块),您可以编写任意函数列表 - 无需将名称作为字符串传递,只需传递函数:

class compose:
    def __init__(self, f, g, *args, **kwargs):
        self.f = f
        self.g = g
        self.pending = args[:]
        self.kwargs = kwargs.copy()
    def __call__(self, *args, **kwargs):
        return self.f(self.g(*args, **kwargs), *self.pending, **self.kwargs)

def transform(value, transformation_list, inverted=False):
    lst = transformation_list if inverted else reversed(transformation_list)
    return reduce(compose, lst)(value)

现在你可以这样打电话给transform

from math import *
value = 2
transformation_list = [sin, sqrt, log]
transform(value, transformation_list)
> -0.047541518047580299

以上将等同于log(sqrt(sin(2)))。如果您需要反转函数应用程序的顺序,例如sin(sqrt(log(2))),请执行以下操作:

transform(value, transformation_list, inverted=True)
> 0.73965300649866683

此外,您可以在线定义功能。例如,F.J的示例使用我的实现看起来像这样:

transform(e, [lambda x:x**3, log, lambda x:x**2])
> 9.0