Conditionally yield nothing in one line in python

4.9k Views Asked by At

I have generator like

def not_nones(some_iterable):
    for item in some_iterable:
        if item is not None:
            yield item

But since "flat is better than nested", I would like to do this in one line, like:

def not_nones(some_iterable):
    for item in some_iterable:
        yield item if item is not None else None

But this will actually make None an item of the generator. Is it possible to yield nothing in a one-liner anyway?

2

There are 2 best solutions below

1
On BEST ANSWER

You could just return a generator expression:

def not_nones(iterable):
    return (item for item in iterable if item is not None)

Or for a real one-liner:

not_nones = lambda it: (i for i in it if i is not None)

which at this point is getting more into code-golf territory.

But really, there's not much wrong with your current code; it does what it needs to do, in a reasonable way. Your code is what I would have written in this situation.

0
On

You could use itertools.ifilter(). Given the right predicate function it provides exactly the functionality you are implementing here.

Example:

import itertools

# make up data
l = [1, None, 2, None, 3]
# predicate function
not_none = lambda x: x is not None
# filter out None values
not_nones = itertools.ifilter(not_none, l)

print list(not_nones) # prints [1, 2, 3]

For reference: