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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.