如何在 itertools.accumulate 中定义自己的函数参数?

How to define own func argument inside itertools.accumulate?

itertools.accumulate的用法如下:

itertools.accumulate(iterable[, func, *, initial=None])

例如

list(itertools.accumulate([0, 7, 19, 13],operator.sub))
# [0, -7, -26, -39]

我使用减法运算符作为 func 参数的地方。

如何定义我自己的 func 参数?

我希望它与 operator.sub 类似,但我需要从第二项中减去第一项,而不是从第一项中减去第二项。

输出 [0, -7, -26, -39] 生成如下:

[0, (0) - (7), (0 - 7) - (19), ((0 - 7) - (19)) - (13)] == [0, -7, -26, -39]

我要:

[0, (7) - (0), (19) - (7 - 0), (13) - ((19) - (7 - 0))] == [0, 7, 12, 1]`

它与 operator.sub 相同,只是交换了减法中参数的顺序。或者换句话说 - 如果 operator.sub 正在做 x1-x2 我希望它在每个迭代步骤中做 x2-x1

创建一个有两个参数的函数,returns 第二个减去第一个的结果:

from itertools import accumulate

def my_sub(a, b):
  return b - a

print(list(accumulate([0, 7, 19, 13], my_sub)))

输出:

[0, 7, 12, 1]

或者您可以使用 lambda:

list(accumulate([0, 7, 19, 13], lambda a, b : b - a))

python 中的一切都是一个对象,可以传递,包括函数。 func 可以是任何可调用对象,包括 lambda、函数、方法和 class 具有 __call__ 方法的任意对象。

以下是这些选项的一些示例:

  1. lambda 是一个特殊的 one-expression 函数,很容易定义。它很方便,因为您可以匿名内联使用它:

     accumulate([0, 7, 19, 13], lambda a, b: b - a)
    

    既然一切都是对象,lambda 不必是匿名的:

     func = lambda a, b: b - a
     accumulate([0, 7, 19, 13], func)
    
  2. 函数可能是最普遍的可调用函数。您使用 def 语句创建一个函数:

     def func(a, b):
         return b - a
     accumulate([0, 7, 19, 13], func)
    

    请注意,当您将它分配给一个名称时,它看起来很像 lambda。 return 单个表达式的 Lambda 和函数在大多数方面的行为几乎完全相同。

    您也可以使用 built-in 函数:

     accumulate([0, 7, 19, 13], operator.rsub)
    

    甚至大多数 class 方法都作为函数存在于 class 对象中。如果你有一个统一的列表,例如所有 ints,你可以利用这个:

     accumulate([0, 7, 19, 13], int.__rsub__)
    

    这是可行的,因为 int.__rsub__ 是一个接受两个参数的函数,它存在于 class int 中。当你做 (3).__rsub__(4) 时,你将该函数绑定到一个实例,这将它变成一个只有一个显式参数的方法。

  3. 一种更深奥的可调用类型是 class 和 __call__ 方法的实例:

     class Subtractor:
         def __call__(self, a, b):
             return b - a
     accumulate([0, 7, 19, 13], Subtractor())
    

    注意 Subtractor() 中的括号。他们创建了一个新实例,它是可调用的,因为 class 定义了 __call__.

  4. function-like 对象的特例是 staticmethodclassmethod 对象。它们不是严格意义上的函数,而是将函数对象包装在 class 中。如果你有实用程序 class,@staticmethod 装饰器可以应用于不依赖于 class 或实例状态的函数:

     class Subtractor:
         @staticmethod
         def func1(a, b):
             return b - a
         @classmethod
         def func2(cls, a, b):
             return b - a
    
     accumulate([0, 7, 19, 13], Subtractor.func1)
     accumulate([0, 7, 19, 13], Subtractor().func2)
    

    func1 表现得像一个普通函数。事实上,它根本不会绑定到一个实例:你也可以做 accumulate([0, 7, 19, 13], Subtractor().func1)。但是,func2 必须绑定到 class 而不是实例。您也可以调用 accumulate([0, 7, 19, 13], Subtractor.func2)