Reputation: 724
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]:
Upvotes: 18
Views: 28281
Reputation: 15204
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.
Upvotes: 31
Reputation: 16720
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.
Upvotes: 8
Reputation: 78556
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 ()]
[]
Upvotes: 5