在reduce函数中传递两个以上的参数

时间:2014-07-30 07:00:27

标签: python python-import reduce

我知道Python reduce只接受带有两个参数的函数。但是,有没有办法让函数可以使用两个以上的参数?我不想让它成为一个全局变量,因为这对所有其他导入都是可见的。以下代码段可能有助于描述问题(请阅读代码段中的注释):

# The reduce function
def apply_something(something, config):
    # Consrtuct a class object based on the truth value of some other variable.
    # some_var can be changed and is being accessed in different threads so its 
    # not safe to make it global. The reduce function is being called from 
    # inside some other function so It would be better to make 
    # some_var only accessible in the function context.

    if some_var:
        obj = Klass(some_var)
    else:
        obj = Klass()

def callee():
    # This is how I apply the reduce operation.
    reduce(apply_something, [1, 2, 3], something_initializer)

    # I want something like this:
    some_var = True  # So this can be accessed in apply_something

请提供一些有关此类问题的见解。

3 个答案:

答案 0 :(得分:7)

我认为你要找的是partial function application,你可以使用functools来做。

def apply_something(something, config, some_var):
    pass  # ...

import functools

reduce(functools.partial(apply_something, some_var=True), 
       [1, 2, 3], something_initializer)

示例:

>>> def foo(a, b, c):
...     return a + b if c else a * b

>>> reduce(functools.partial(foo, c=True), [1,2,3,4,5], 0)
15

>>> reduce(functools.partial(foo, c=False), [1,2,3,4,5], 1)
120

答案 1 :(得分:2)

严格地说,传递给reduce的函数将始终使用两个参数调用。但是,这些类型的函数通常会访问外部作用域中的变量。由于我不确定您的确切问题,因此请在join方面实施reduce

def join(joining_string, strings_to_join):
    # i.e., join('-', ['a', 'b', 'c']) -> 'a-b-c'
    # Here, we need an extra piece of data in our reduce function:
    #   joining_string.

    def do_reduce(a, b):
        # Joining string comes from the outer scope:
        return a + joining_string + b

    return reduce(do_reduce, strings_to_join)

此外,Chris Martin的partial解决方案也完全正确。将其应用于上述内容将如下所示:

# This didn't *need* to move out of join, but it can. Before, it needed
# to be in join to be able to "capture" the local variable joining_string.
def do_reduce(a, b, joiner):
    # Joining string comes from the outer scope:
    return a + joiner + b


def join(joining_string, strings_to_join):
    # i.e., join('-', ['a', 'b', 'c']) -> 'a-b-c'
    # Here, we need an extra piece of data in our reduce function:
    #   joining_string.

    return reduce(
        functools.partial(do_reduce, joiner=joining_string),
        strings_to_join)

答案 2 :(得分:1)

您也可以使用lambda

def foo(total, cur, some_var=False):
    pass  # ...

reduce(lambda total, cur: foo(total, cur, some_var=True), [1, 2, 3], init)