Python 函数实现的保序性

Python 函数实现的保序性,python,function,functional-programming,composition,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

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

假设我有一个数字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之类的东西,因为随着我添加更多的转换,它会变得丑陋
我应该如何设计它。

类似于以下的东西应该可以工作:

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

类似于以下的方法应该可以工作:

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
使用此函数组合(或者使用模块),您可以组合任意函数列表-无需将名称作为字符串传递,只需传递函数:

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
使用此函数组合(或者使用模块),您可以组合任意函数列表-无需将名称作为字符串传递,只需传递函数:

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

转换列表必须是字符串列表吗?您可以只传递一个函数列表(
来自路径导入日志;def square(x):返回x*x;transform(8,[log,square])
)。您可以将其作为解决方案编写并解释一下吗?它不必是一个列表??这可能不是一个答案,但我的观点是:与传递字符串列表不同,您可以通过传递函数列表使事情变得更简单和更可扩展。转换列表必须是字符串列表吗?您可以只传递一个函数列表(
来自路径导入日志;def square(x):返回x*x;transform(8,[log,square])
)。您可以将其作为解决方案编写并解释一下吗?它不必是一个列表??这可能不是一个答案,但我的观点是:与传递字符串列表不同,您可以通过传递函数列表使事情变得更简单和更可扩展。