PyCharm (4.0.6) complains when I do a comparison to an empty list using the ==
operator, but it doesn't when I use the is
operator:
I guess this is something related to PEP 8, but the problem is that when I use the is
operator, as PyCharm suggests, I have a false negative. Here is a simple example in iPython shell to show that in this case the ==
operator seems more appropriate, since the is
operator returns a false negative:
In[2]: actions = []
In[3]: actions == []
Out[3]: True
In[4]: actions is []
Out[4]: False
Could someone please explain why PyCharm complains about the ==
operator when comparing to an empty lists? Am I doing something wrong according to PEP 8?
Usually, an empty list has a different meaning than None ; None means no value while an empty list means zero values.
Empty lists are considered False in Python, hence the bool() function would return False if the list was passed as an argument. Other methods you can use to check if a list is empty are placing it inside an if statement, using the len() methods, or comparing it with an empty list.
The empty list, [] , is not equal to None . However, it can evaluate to False --that is to say, its "truthiness" value is False .
In Python, empty list object evaluates to false. Hence following conditional statement can be used to check if list is empty.
Quoting PEP-8's Programming Recommendations section,
For sequences, (strings, lists, tuples), use the fact that empty sequences are false.
Yes: if not seq: if seq: No: if len(seq) if not len(seq)
Since empty sequences are Falsy in Python,
>>> bool([])
False
>>> bool(())
False
you can simply use if not
as mentioned in the PEP-8.
Note: You should never use is
to compare if two values are equal, because is
operator checks if two objects are one and the same, but ==
checks if two objects are equal.
I dug in to the source code to figure out what is happening. When we do a == []
,
>>> dis(compile('if a == []: pass', "string", "exec"))
1 0 LOAD_NAME 0 (a)
3 BUILD_LIST 0
6 COMPARE_OP 2 (==)
9 POP_JUMP_IF_FALSE 15
12 JUMP_FORWARD 0 (to 15)
>> 15 LOAD_CONST 0 (None)
18 RETURN_VALUE
we are constructing a new list and it would be a very costly operation, just for comparison. On the other hand
>>> dis(compile('if not a: pass', "string", "exec"))
1 0 LOAD_NAME 0 (a)
3 POP_JUMP_IF_TRUE 9
6 JUMP_FORWARD 0 (to 9)
>> 9 LOAD_CONST 0 (None)
12 RETURN_VALUE
we are trying to see if the current sequence could be Truthy. This internally checks if the length of the sequence is zero (which is just a simple lookup, as the length of the list is maintained in a variable). If the length is zero, then if not actions:
will be Truthy. Here we don't construct a new list, but we are just checking the length implicitly, instead of explicitly doing
if len(actions) == 0:
So, I am guessing that Python Gurus are suggesting if not seq
because there could be performance advantage as well.
According to PEP8 doc you should use
For sequences, (strings, lists, tuples), use the fact that empty sequences are false.
Yes: if not seq:
if seq:
No: if len(seq)
if not len(seq)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With