如何创建一个可以迭代数组中的项目中任意数量的函数的函数?

How to create a function that can iterate over an arbitrary number of functions within an item within an array?

我有一个名为 function_iterate_over_array 的函数,它接受一个数组和一个函数名称列表。虽然该函数确实有效,但我需要创建一个函数来实现相同的结果但可以接受任意数量的 function_names。

例如下面的函数必须接受四个函数名

from operator import itemgetter
from itertools import groupby
from dictionary_functions import DictionaryFunctions

group_func = lambda iterable,key:  [list(group) for key, group in groupby(sorted(iterable, key=itemgetter(key)), itemgetter(key))]

def add_one(i):
    return i + 1
def subtract_one(i):
    return i - 1


array = [{'f1':add_one,'f2':add_one,'f3':add_one,'f4':add_one},
{'f1':add_one,'f2':add_one,'f3':add_one,'f4':add_one},
{'f1':subtract_one,'f2':subtract_one,'f3':subtract_one,'f4':subtract_one},
{'f1':subtract_one,'f2':add_one,'f3':add_one,'f4':add_one}]

functions = ['f1','f2','f3','f4']

def function_iterate_over_array(array,functions,starting_value=0):
    L = []
    function_key_name = functions[0]
    grouped_array = group_func(array,function_key_name)
    for grouped_array_item in grouped_array:
        function_one = grouped_array_item[0][function_key_name]
        function_one_result = function_one(starting_value)

        function_two_name = functions[1]
        sub_grouped_array = group_func(grouped_array_item,function_two_name)
        for sub_grouped_array_item in sub_grouped_array:
            function_two = sub_grouped_array_item[0][function_two_name]
            function_two_result = function_two(function_one_result)


            function_three_name = functions[2]
            sub_sub_grouped_array = group_func(sub_grouped_array_item,function_three_name)
            for sub_sub_grouped_array_item in sub_sub_grouped_array:
                function_three = sub_sub_grouped_array_item[0][function_three_name]
                function_three_result = function_three(function_two_result)


                function_four_name = functions[3]
                sub_sub_sub_grouped_array = group_func(sub_sub_grouped_array_item,function_four_name)
                for sub_sub_sub_grouped_array_item in sub_sub_sub_grouped_array:
                    function_four = sub_sub_sub_grouped_array_item[0][function_four_name]
                    function_four_result = function_four(function_three_result)


                    for dictionary_from_array in sub_sub_sub_grouped_array_item:
                        D = dict(dictionary_from_array.items()+{'result':function_four_result}.items())
                        L.append(D)

    return L 



L = function_iterate_over_array(array,functions)
#-->[{'f1': <function add_one at 0x1006d5cf8>, 'f2': <function add_one at 0x1006d5cf8>, 'f3': <function add_one at 0x1006d5cf8>, 'f4': <function add_one at 0x1006d5cf8>, 'result': 4}, {'f1': <function add_one at 0x1006d5cf8>, 'f2': <function add_one at 0x1006d5cf8>, 'f3': <function add_one at 0x1006d5cf8>, 'f4': <function add_one at 0x1006d5cf8>, 'result': 4}, {'f1': <function subtract_one at 0x100763ed8>, 'f2': <function add_one at 0x1006d5cf8>, 'f3': <function add_one at 0x1006d5cf8>, 'f4': <function add_one at 0x1006d5cf8>, 'result': 2}, {'f1': <function subtract_one at 0x100763ed8>, 'f2': <function subtract_one at 0x100763ed8>, 'f3': <function subtract_one at 0x100763ed8>, 'f4': <function subtract_one at 0x100763ed8>, 'result': -4}]

我想用比 function_iterate_over_array 更好的函数实现相同的结果,它可以接受任意数量的函数。例如,我希望以下内容起作用:

array = [{'f1':add_one,'f2':add_one,'f3':add_one,'f4':add_one},
{'f1':add_one,'f2':add_one,'f3':add_one,'f4':add_one},
{'f1':subtract_one,'f2':subtract_one,'f3':subtract_one,'f4':subtract_one},
{'f1':subtract_one,'f2':add_one,'f3':add_one,'f4':add_one}]
function_iterate_over_array(array,['f1','f2'])

function_iterate_over_array(array,['f1','f2']) 应该 return 以下内容:

[{'f1': <function add_one at 0x101a0fcf8>, 'f2': <function add_one at 0x101a0fcf8>, 'f3': <function add_one at 0x101a0fcf8>, 'f4': <function add_one at 0x101a0fcf8>, 'f5': <function add_one at 0x101a0fcf8>, 'result': 2}, {'f1': <function add_one at 0x101a0fcf8>, 'f2': <function add_one at 0x101a0fcf8>, 'f3': <function add_one at 0x101a0fcf8>, 'f4': <function add_one at 0x101a0fcf8>, 'f5': <function add_one at 0x101a0fcf8>, 'result': 2}]

我通过将 function_iterate_over_array 更改为以下内容来实现:

def function_iterate_over_array(array,functions,starting_value=0):
    L = []
    function_key_name = functions[0]
    grouped_array = group_func(array,function_key_name)
    for grouped_array_item in grouped_array:
        function_one = grouped_array_item[0][function_key_name]
        function_one_result = function_one(starting_value)

        function_two_name = functions[1]
        sub_grouped_array = group_func(grouped_array_item,function_two_name)
        for sub_grouped_array_item in sub_grouped_array:
            function_two = sub_grouped_array_item[0][function_two_name]
            function_two_result = function_two(function_one_result)


            for dictionary_from_array in sub_grouped_array_item:
                D = dict(dictionary_from_array.items()+{'result':function_two_result}.items())
                L.append(D)
    return L 

我也希望下面的工作正常

array = [{'f1':add_one,'f2':add_one,'f3':add_one,'f4':add_one,'f5':add_one},
{'f1':add_one,'f2':add_one,'f3':add_one,'f4':add_one,'f5':add_one}]
functions = ['f1','f2','f3','f4','f5']
function_iterate_over_array(array,functions)

特别是我正在寻找一种更好的方法来编写上述函数,以便它可以接受任意数量的函数。

看来reduce可以帮到你很多。

Apply function of two arguments cumulatively to the items of iterable, from left to right, so as to reduce the iterable to a single value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5). The left argument, x, is the accumulated value and the right argument, y, is the update value from the iterable. If the optional initializer is present, it is placed before the items of the iterable in the calculation, and serves as a default when the iterable is empty. If initializer is not given and iterable contains only one item, the first item is returned.

它专门设计用于将函数反复应用于值集合。使用 lambda,您可以在每个步骤中使用不同的函数。

from functools import reduce

def add_one(i):
    return i + 1

def subtract_one(i):
    return i - 1

function_dicts = [{'f1':add_one,'f2':add_one,'f3':add_one,'f4':add_one},
{'f1':subtract_one,'f2':subtract_one,'f3':subtract_one,'f4':subtract_one},
{'f1':subtract_one,'f2':add_one,'f3':add_one,'f4':add_one}]

functions = ['f1','f2','f3','f4']

for function_dict in function_dicts:
    result = reduce((lambda value, fname : function_dict[fname](value)), functions, 0)
    print(result)
# 4 
# -4
# 2

它 return 与您问题中的格式不完全相同,但这提供了所需的核心功能。

这似乎非常接近,尽管顺序不同。我无法理解那种人应该做什么。如果你需要帮助恢复它,你能解释一下那里的目标吗? (请注意,在 Python 3 中,您的排序甚至不起作用,因为函数不可排序。)

import pprint

def add_one(i):
    return i + 1
def subtract_one(i):
    return i - 1

function_dictionaries = [
    {'f1': add_one, 'f2': add_one, 'f3': add_one, 'f4': add_one},
    {'f1': add_one, 'f2': add_one, 'f3': add_one, 'f4': add_one},
    {'f1': subtract_one, 'f2': subtract_one, 'f3': subtract_one, 'f4': subtract_one},
    {'f1': subtract_one, 'f2': add_one, 'f3': add_one, 'f4': add_one}
]

def apply_functions(function_dictionaries, function_names, starting_value=0):
    results = []
    for d in function_dictionaries:
        result = d.copy()
        value = starting_value
        for function_name in function_names:
            value = d[function_name](value)
        result['result'] = value
        results.append(result)
    return results

pprint.pprint(apply_functions(function_dictionaries, ['f1', 'f2', 'f3', 'f4']))

# Output:
# [{'f1': <function add_one at 0x10ae58048>,
#   'f2': <function add_one at 0x10ae58048>,
#   'f3': <function add_one at 0x10ae58048>,
#   'f4': <function add_one at 0x10ae58048>,
#   'result': 4},
#  {'f1': <function add_one at 0x10ae58048>,
#   'f2': <function add_one at 0x10ae58048>,
#   'f3': <function add_one at 0x10ae58048>,
#   'f4': <function add_one at 0x10ae58048>,
#   'result': 4},
#  {'f1': <function subtract_one at 0x10aec4048>,
#   'f2': <function subtract_one at 0x10aec4048>,
#   'f3': <function subtract_one at 0x10aec4048>,
#   'f4': <function subtract_one at 0x10aec4048>,
#   'result': -4},
#  {'f1': <function subtract_one at 0x10aec4048>,
#   'f2': <function add_one at 0x10ae58048>,
#   'f3': <function add_one at 0x10ae58048>,
#   'f4': <function add_one at 0x10ae58048>,
#   'result': 2}]