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.