在 reduce 函数中传递超过两个参数

6

我知道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

请提供关于这类问题的一些见解。

5
请问您需要翻译的内容是:"It is not clear to me how this is a reduce function. Can you give an example input, and show how it would reduce that input?" 我不太清楚这是如何成为一个reduce函数。您能给出一个输入示例,并展示它如何对该输入进行规约吗? - Thanatos
@Thanatos,我修改了问题。你能否请审核一下? - Rafay
3个回答

15

我认为您正在寻找的是部分应用函数,您可以使用functools来实现。

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

import functools

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

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

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

3

严格来说,传递给reduce的函数始终将使用两个参数调用。但是这些类型的函数通常会访问外部作用域中的变量。由于我不清楚您确切的问题,让我们使用reduce来实现join

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)

0

你也可以使用lambda函数:

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接