我知道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
请提供一些有关此类问题的见解。
答案 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)