pythonfunctional-programmingfluent

Python fluent filter, map, etc


I love python. However, one thing that bugs me a bit is that I don't know how to format functional activities in a fluid manner like a can in javascript.

example (randomly created on the spot): Can you help me convert this to python in a fluent looking manner?

var even_set = [1,2,3,4,5]
.filter(function(x){return x%2 === 0;})
.map(function(x){
    console.log(x); // prints it for fun
    return x;
})
.reduce(function(num_set, val) {
    num_set[val] = true;
}, {});

I'd like to know if there are fluid options? Maybe a library.

In general, I've been using list comprehensions for most things but it's a real problem if I want to print

e.g., How can I print every even number between 1 - 5 in python 2.x using list comprehension (Python 3 print() as a function but Python 2 it doesn't). It's also a bit annoying that a list is constructed and returned. I'd rather just for loop.


Solution

  • Generators, iterators, and itertools give added powers to chaining and filtering actions. But rather than remember (or look up) rarely used things, I gravitate toward helper functions and comprehensions.

    For example in this case, take care of the logging with a helper function:

    def echo(x):
        print(x)
        return x
    

    Selecting even values is easy with the if clause of a comprehension. And since the final output is a dictionary, use that kind of comprehension:

    In [118]: d={echo(x):True for x in s if x%2==0}
    2
    4
    
    In [119]: d
    Out[119]: {2: True, 4: True}
    

    or to add these values to an existing dictionary, use update.

    new_set.update({echo(x):True for x in s if x%2==0})
    

    another way to write this is with an intermediate generator:

    {y:True for y in (echo(x) for x in s if x%2==0)}
    

    Or combine the echo and filter in one generator

    def even(s):
        for x in s:
            if x%2==0:
                print(x)
                yield(x)
    

    followed by a dict comp using it:

    {y:True for y in even(s)}