I am aware that Python reduce only accepts a function with two arguments. However, is there a way to make more than two arguments available to the function? I don't want to make it a global variable because that would be visible for all other imports. The following snippet might help describing the problem (Please read the comments in the snippets):
# 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
Please provide some insight into this kind of problem.
I think what you're looking for is partial function application, which you can do using 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)
Example:
>>> 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
Strictly speaking, the function passed to reduce will always be called with two arguments. However, these types of functions will often access variables in an outer scope. Since I'm unclear on your exact problem, let's implement join
in terms of 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)
Also, Chris Martin's solution involving partial
is perfectly correct as well. Applying it to the above would look like this:
# 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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With