# Which solution is good to generate a list without None results from a function? [closed]

I'm relatively new to Python and learned, that function cannot return nothing, not even None. In my application I want to iterate over a list and keep all non-None results of a complicated function:

def complicated_function(x):
if x < 0:
return "a"
elif x == 3.6:
return "b"
elif x == 4:
return None  # Idealy here nothing should be returned
elif x > 10:
return "c"
else:
return "d"


I have three soltuions and my question is which would you recommend me to use and are there better ones?

### First solution

tmp = [complicated_function(x) for x in [-1, 2, 3.6, 4, 5, 20]]
ret = [x for x in tmp if x]


### Second solution

ret = [complicated_function(x) for x in [-1, 2, 3.6, 4, 5, 20] if complicated_function(x)]


### Third solution

ret = []
for x in [-1, 2, 3.6, 4, 5, 20]:
tmp = complicated_function(x)
if tmp:
ret.append(tmp)


I think the first solution is slow, if the list to iterate over is very large. The second solution seems to be bad if the complated_function is really expensive (in rumtime). The third solution seems to be ok, but append is said to be significantly slower than list comprehension.

• Which Python version are you using? In Python 3.8+ you can make your list comprehension less expensive by calling the function only once using the walrus operator. – Graipher Mar 20 at 11:13
• @Graipher How would the walrus operator work? – Qaswed Mar 20 at 14:36
• ret = [y for x in [-1, 2, 3.6, 4, 5, 20] if (y := complicated_function(x))] – Graipher Mar 20 at 14:45
• @Graipher Thanks for your explanaition of the walrus operator. I'm using Python 3.7, but definitely will keep this in mind as an option when switching to 3.8. – Qaswed Mar 20 at 15:00
• stackoverflow.com/a/48609910/7311767 – Stephen Rauch Mar 20 at 15:26

You can use an intermediate generator function:

[y for y in (complicated_function(x) for x in <my_iterable>) if y is not None]


An alternative is changing complicated_function to become a generator that accepts an iterable, instead of a pure function:

def complicated_function(iterable):
for x in iterable:
if x < 0:
yield "a"
elif x == 3.6:
yield "b"
elif x == 4:
continue
elif x > 10:
yield "c"
else:
yield "d"


and then: list(complicated_function(<my_iterable>))