简体   繁体   中英

How to define own func argument inside itertools.accumulate?

The usage of itertools.accumulate is as follows:

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

For example

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

Where I used subtraction operator as func argument.

How to define my own func argument?

I want it similar to operator.sub but instead of subtracting second item from first item I need to subtract first item from second item.

The output [0, -7, -26, -39] was produced as follows:

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

I want it:

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

It is same as with operator.sub just the order of arguments inside subtraction is swapped. Or other way said - if operator.sub is doing x1-x2 I want it to do x2-x1 at each iteration step.

Everthing is an object in python, and can be passed around, including functions. func can be any callable, which includes lambdas, functions, methods, and arbitrary objects whose class has a __call__ method.

Here are some examples of these options:

  1. A lambda is a special one-expression function that is is very easy to define. It's handy because you can use it anonymously inline:

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

    Since everything is an object, the lambda doesn't have to be anonymous:

     func = lambda a, b: b - a accumulate([0, 7, 19, 13], func)
  2. Functions are probably the most ubiquitous callable. You make a function with the def statement:

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

    Notice that this looks a lot like the lambda when you assign it to a name. Lambdas and functions that return a single expression behave almost exactly the same in most regards.

    You can use a built-in function as well:

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

    Even most class methods exist as functions in the class object. If you have a uniform list, eg, all int s, you can take advantage of this:

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

    This works because int.__rsub__ is a function accepting two arguments, which lives in the class int . When you do (3).__rsub__(4) , you bind that function to an instance, which turns it into a method with just one explicit argument.

  3. A more esoteric type of callable is an instance of a class with a __call__ method:

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

    Notice the parentheses in Subtractor() . They create a new instance, which is callable because the class defines __call__ .

  4. A special case of function-like objects are staticmethod and classmethod objects. They are not strictly functions, but wrap function objects inside a class. If you have a utility class, the @staticmethod decorator could be applied to a function that does not rely on the class or instance state:

     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 behaves like a normal function. In fact, it won't bind to an instance at all: you can also do accumulate([0, 7, 19, 13], Subtractor().func1) . func2 , however, must be bound, but to the class and not the instance. You could call accumulate([0, 7, 19, 13], Subtractor.func2) as well.

Create a function with two arguments, that returns the result of subtracting the first from the second:

from itertools import accumulate

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

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

Output:

[0, 7, 12, 1]

Or you could use a lambda :

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM