19

I am somehow familiar with list comprehensions in Python. But in situations when I need to check if the list is not None, the list comprehension would fail.

e.g.

tags = v.tags if tags: for t in tags: if t['Key'] == 'Name': # Do something 

Now, if tags is None, then the following list comprehension fails. It works fine if tags is empty/[]. I would like a list comprehension that checks against None.

[k for k,v in tags if tags]: 
3
  • you are trying to loop over tags.. You can do this with empty collectors ([], (), {}) but not over None. Commented Jun 28, 2017 at 15:44
  • Why do you need a list comprehension. Commented Jun 28, 2017 at 15:47
  • 4
    Shortest way: [k for k,v in (tags or [])] Commented Jun 28, 2017 at 15:47

3 Answers 3

31

How about this:

[k for k in (tags or [])] 

Let's see what happens for both cases:

  • >>> tags = None

    >>> [k for k in (tags or [])] [] 
  • tags = [1, 2, 3]

    >>> [k for k in (tags or [])] [1, 2, 3] 

The reason this works is because (tags or []) returns tags only if bool(tags) == True. Otherwise it returns the second argument, in this case [], even if its boolean value is also False. That way, we either loop over tags, if it exists` or over an empty list if it doesn't.

Sign up to request clarification or add additional context in comments.

1 Comment

Brilliant! A clean solution that avoids an if statement to check if the object is not None.
9

You can use a ternary condition here:

([k for k, v in tags] if tags is not None else []) 

You can embed the ternary condition in the comprehension as well:

[k for k, v in (tags if tags is not None else [])] 

As a side note, [k for k, v in tags if tags] does not really behave as you might expect. The if clause of a list comprehension is evaluated at each iteration, meaning that the truth value of tags is checked for each element in it.

To prove this:

l = [1, 2, 3, 4, 5] def is_empty(l): print("is_empty") return len(l) > 0 m = [i for i in l if is_empty(l)] print(m) 

Output:

is_empty is_empty is_empty is_empty is_empty [1, 2, 3, 4, 5] 

What you are semantically looking for is an inline if, that is, in Python, a ternary condition.

Comments

5

You can test with a preceding if block

if tags is not None: ... 

Or short-circuit with an empty iterable:

>>> tags = None >>> [k for k, _ in tags or ()] [] 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.