【问题标题】:Python: Reduce() and function as argument of functionPython:Reduce() 和函数作为函数的参数
【发布时间】:2020-04-27 11:12:03
【问题描述】:

在 Python3 中,我试图弄清楚 reduce() 和函数作为函数的参数,或者更好地将函数作为另一个函数的参数传递,其中第一个函数不明确,见下文

给定:

# define a function `call` where you provide the function and the arguments
def call(y,f):
    return f(y)

# define a function that returns the square
square = lambda x : x*x

# define a function that returns the increment
increment = lambda x : x+1

# define a function that returns the cube
cube = lambda x : x*x*x

# define a function that returns the decrement
decrement = lambda x : x-1

# put all the functions in a list in the order that you want to execute them
funcs = [square, increment, cube, decrement]

#bring it all together. Below is the non functional part. 
#in functional programming you separate the functional and the non functional parts.
from functools import reduce # reduce is in the functools library
print(reduce(call, funcs,1)) # output 7 , 2  res 124

为什么它不起作用,如果

我变了

def call(y,f)
       f(y)

def call(f,y)
       f(y)

并给出错误:

................py", line 27, in call
    return f(y)

TypeError: 'int' object is not callable

【问题讨论】:

标签: python python-3.x function arguments


【解决方案1】:

functools.reduce()

要理解这一点,我们首先要了解reduce是如何工作的,reduce需要3个参数:

  • 一个函数
  • 一个可迭代的元素
  • 一个初始化器。

让我们关注函数和可迭代元素来了解函数是如何调用的

以下是functools的官方文档:

functools.reduce(function, iterable[, initializer])

应用函数 两个参数累积到可迭代的项目,从左到 对,以便将可迭代减少为单个值。例如, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) 计算 ((((1+2)+3)+4)+5)。左边的参数 x 是累积值,并且 正确的参数 y 是来自可迭代对象的更新值。如果 可选初始化器存在,它被放置在项目之前 在计算中可迭代,并在可迭代时用作默认值 是空的。如果没有给出初始化程序并且可迭代只包含一个 item,返回第一个 item。

大致相当于:

def reduce(function, iterable, initializer=None):
    it = iter(iterable)
    if initializer is None:
        value = next(it)
    else:
        value = initializer
    for element in it:
        value = function(value, element)
    return value

这里你可以理解,它接受第一个参数中传递的函数,并以值、元素作为传递函数的参数来执行它。请注意,元素是第二个参数iterable 中的每个element。所以当你打电话给reduce(call, funcs, 1)时,

发生了以下情况: 由于initializer=1,value=initializer,

对于 funcs 中的每个 func,都发生了以下情况

调用(1,函数)

TLDR; 当您替换 y 和 f 时,您正在尝试调用 1(func),这是不可能的,这就是第一个初始解决方案有效的原因,因为它调用了 func(1)

参考:Python Docs - functools

【讨论】:

  • 感谢乌达亚。仍然让我感到困惑,但有点明白了。在我的情况下,initializer = 1 然后调用 y=1 所以 f(1) 在交换 y 和 ,1(f) 时有意义,这是不可能的?
  • 没错。这与您得到的错误 'int' object is not callable 产生了共鸣。
  • 另外,如果你不传递任何初始化器,请记住它会将可迭代的第一个元素作为value 用于第一次调用函数
  • 如果您觉得这个答案令人满意,请确保将其标记为正确的答案:)