-1

Let's say I have three functions and it needs to process a list one after another.

def f1(lst):
    lst_processed = do_something_of_type1(lst)
    return lst_processed

def f2(lst):
    lst_processed = do_something_of_type2(lst)
    return lst_processed

def f3(lst):
    lst_processed = do_something_of_type3(lst)
    return lst_processed

I would like to apply these three functions on some input_list in the following order: f1, then f2 since f2 needs the processed list from f1 and finally f3 which needs the return value of f2.

Option 1:

output_list = f3(f2(f1(input_list)))

Option 2:

   output_list1 = f1(input_list)
   output_list2 = f2(output_list1)
   output_list = f3(output_list2)

Does one of these comply with PEP 8 more so than the other?

utengr
  • 3,225
  • 3
  • 29
  • 68
  • 1
    Do you need three separate functions? Why not just have one that does all the processing? Or create a class where your can do method chaining. – It_is_Chris Aug 24 '21 at 13:13
  • @It_is_Chris I do need all three functions as I have divided different type of processing in them. Class might be too complex for such situation but of course that could be an option. I am just interested in choosing these two options. – utengr Aug 24 '21 at 13:16
  • I am also wondering why would be class method chaining preferred in this case over option 1? – utengr Aug 24 '21 at 13:24
  • It really is going to depend on your specific use. If it is something will will be used across multiple .py files and/or if you need to call the functions in a different order `f3(f1(input_list))` or some other variation. It may be easier to just do `Foo(input_list).f1().f3()` – It_is_Chris Aug 24 '21 at 13:28
  • The methods are used in different situations. In some cases, I will be using just f1, or f2 or f3 or f3.f2 or f2.f1 so they are bit different general purpose but my question was more about once one has such a specific situation in question, then which option is better. – utengr Aug 24 '21 at 13:30
  • I would question the function separation. If there is a valid reason to separate them. IIRC isnt it a Python antipattern to have linked dependencies unnecessarily? – Jason Chia Aug 24 '21 at 13:31

5 Answers5

2

From this answer: Is there a chain calling method in Python?

def f1(i):
    return i + 1


def f2(i):
    return i + 1


def f3(i):
    return i + 1


def f4(i):
    return i + 1


from functools import reduce


def chain(*funcs):
    def chained_call(arg):
        return reduce(lambda r, f: f(r), funcs, arg)

    return chained_call


chained = chain(f1, f2, f3, f4)

print(chained(0))
ted
  • 13,596
  • 9
  • 65
  • 107
1

I don't think there's actually anything built-in to do this (functools seemed like the most likely place to find something), but it's also relatively easy to write the kind of thing you'd find there

def chainfunc(funcs, arg):
    ret = arg
    for f in funcs:
        ret = f(arg)
    return ret

output_list = chainfunc([f1, f2, f3], lst)

That said, you can also coerce functools.reduce() into doing something like this in a one-liner:

from functools import reduce

output_list = reduce(lambda a, b: b(a), [f1, f2, f3], lst)
Green Cloak Guy
  • 23,793
  • 4
  • 33
  • 53
0

option 1 is more pythonic, but depends for whom you are writing your code. For my opinion option 2 is more readable for junior developers. Have you searched the pep8 documentation?

Dharman
  • 30,962
  • 25
  • 85
  • 135
Adam Zaft
  • 1
  • 3
0

I would put option 2 in a function of it’s own, and then call that. Also, I wouldn’t call them f1, f2, etc.

Ezra
  • 471
  • 3
  • 14
-4

Why do you need 3 functions?

def f(lst):
   lst_1 = do_something_of_type1(lst)
   lst_2 = do_something_of_type2(lst_1)
   lst_processed = do_something_of_type3(lst_2)
return lst_processed
babeyh
  • 659
  • 2
  • 7
  • 19
  • I assume the functions are 1. not just useful in this context, and 2. split up for organization, etc. – Ezra Aug 24 '21 at 13:16
  • Is this an attempt at answering the question? If so, please edit the answer to make it clear how this answers the question. – TylerH Aug 24 '21 at 14:31