【问题标题】:How to define own func argument inside itertools.accumulate?如何在 itertools.accumulate 中定义自己的 func 参数?
【发布时间】:2021-02-06 00:20:44
【问题描述】:

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

【问题讨论】:

    标签: python function iteration itertools


    【解决方案1】:

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

    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))
    

    【讨论】:

    • 这是最简单的方法吗?像-operator.sub 这样的东西不起作用?
    • 这是一个使用 lambda 的好地方,但我不认为 赶时间 是一个很好的论据;)
    • 哦...我更喜欢使用lambda 的方式。谢谢。
    • @azerbajdzan 你不能使用-operator.suboperator.sub 是一个函数,你不能将一个函数设为负数,你可以根据operator.sub 构建你的函数,就像这样,例如:lambda a, b : -operator.sub(a, b).
    • 回答阿塞拜疆的问题。不,那行不通。但我也想说 Python 不咬人。如果不确定,试试吧!看看会发生什么。
    【解决方案2】:

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

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

    1. lambda 是一个特殊的单表达式函数,非常容易定义。它很方便,因为您可以匿名内联使用它:

       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。返回单个表达式的 Lambda 和函数在大多数方面的行为几乎完全相同。

      您也可以使用内置函数:

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

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

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

      这是因为int.__rsub__ 是一个接受两个参数的函数,它位于int 类中。当您执行(3).__rsub__(4) 时,您将该函数绑定到一个实例,这会将其转换为只有一个显式参数的方法。

    3. 更深奥的可调用类型是具有__call__ 方法的类的实例:

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

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

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

       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 必须绑定,但必须绑定到类而不是实例。您也可以拨打accumulate([0, 7, 19, 13], Subtractor.func2)

    【讨论】:

    • func2 始终与类绑定,您也可以使用Subtractor.func2,因此您的最后一句话具有误导性。否则很好的答案!
    • @Jasmijn。你说得对。固定的。我在想继承会发生什么,但这在这里无关紧要。
    猜你喜欢
    • 2022-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-24
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多