azerbajdzan
azerbajdzan

Reputation: 169

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.

Upvotes: 3

Views: 1001

Answers (2)

Mad Physicist
Mad Physicist

Reputation: 114440

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, e.g., all ints, 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.

Upvotes: 3

Djaouad
Djaouad

Reputation: 22776

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

Upvotes: 1

Related Questions