All objects in Python have a boolean value; they are either true or false in a boolean context.
Empty lists are false. This applies to all sequences and containers, including tuples, sets, dictionaries, and strings.
The numerical value of 0 is also false, so 0, 0.0, 0j are also false, like None and, of course, False :
>>> bool([]) False >>> bool([1, 2]) True >>> bool(0) False >>> bool('') False
Everything else is considered true in a boolean context; therefore, a list that is not empty is true, and two non-empty lists along with and also considered true.
You can make custom types look like empty containers by implementing __len__() and returning 0 , or look at a number by doing __nonzero__() * and return False when the instance should be the logical equivalent of a numeric zero.
Just remember that and and or shortcircuit; if the first expression is blocked as a result, then this value is returned, and the second expression is ignored altogether. For and this means that in the expression x and y , y ignored if x is a false value (for example, an empty list), because in this case the whole expression cannot be true. For x or y , y ignored if x is a true value.
All of these rules are covered by the Boolean reference documentation .
* In Python 3, use __bool__ instead .