What Counts as Empty, False, or Equal
Python will evaluate almost anything as true or false, including things that are neither. Feed in an empty list, the number zero, and the string that spells the word False, and see which ones the language actually treats as false.
Read first: Ordered Collections, Two Ways
Python will evaluate almost anything as true or false, including things that are neither. Feed in an empty list, the number zero, and the string that spells the word False, and see which ones the language actually treats as false.
What counts as empty
Write if some_list: instead of if len(some_list) > 0: and Python will do exactly what you mean — but only because it treats every empty collection, and the number zero, as false.
What Python treats as false
Everything below is falsy. Every other value in the language, no matter how it looks, is truthy.
- •0 and 0.0 — but no other number, including -1.
- •"" — the empty string, and only the empty string.
- •[], {}, and set() — an empty list, dictionary, or set.
- •None — Python's stand-in for "no value at all".
- •False itself, which is where the whole idea starts.
The list is short, and the trap is what is missing from it. The string "False" is not empty — it has five characters in it — so it is truthy, despite spelling out the word. A list holding a single 0 is not empty either; it has one item, so it too is truthy.
$ >>> bool(0)$ False$ >>> bool("False")$ True$ >>> bool([])$ False$ >>> bool([0])$ True>>> bool(0)
False
Only 0, "", [], {}, and None count as false. The string "False" is not empty, so it is true — a common surprise the first time you read a value from user input and check it directly.
Empty does not mean missing
if x: treats an empty list, the number 0, and None as exactly the same kind of false. Most of the time that is fine. It stops being fine the moment an empty list or a zero is a valid answer you still need to tell apart from no answer having arrived at all.
$ >>> def summarise(votes=None):$ ... if votes:$ ... print(f"{len(votes)} votes counted")$ ... else:$ ... print("no votes yet")$ ...$ >>> summarise([])$ no votes yet$ >>> summarise([1, 2, 3])$ 3 votes countedThe round with zero votes and the round that has not started yet print the identical message, because [] and None both fail if votes:. Ask the narrower question instead, and the two cases separate:
$ >>> def summarise(votes=None):$ ... if votes is not None:$ ... print(f"{len(votes)} votes counted")$ ... else:$ ... print("no votes yet")$ ...$ >>> summarise([])$ 0 votes countedThe same value is not the same object
== asks whether two things hold equal values. is asks whether two names point at the exact same object sitting in memory. Almost every comparison you write wants ==.
$ >>> a = [1, 2, 3]$ >>> b = [1, 2, 3]$ >>> a == b$ True$ >>> a is b$ Falsea and b are two separate lists that happen to hold equal contents, built on two separate lines. is sees straight through the equal values to the fact that they are different objects — change a, and b does not move.
The one place is is the right tool, always, is comparing against None. None is a single object that exists exactly once for the whole program, so identity is precisely the question you mean to ask.
$ >>> x = None$ >>> x is None$ TrueA collection that refuses duplicates
A set is an unordered collection that will not hold the same value twice — add a duplicate, and nothing happens, silently.
$ >>> tags = ["python", "beginner", "python", "tutorial"]$ >>> set(tags)$ {'python', 'beginner', 'tutorial'}Turning a list into a set is the fastest way to deduplicate it. Notice the order is not preserved — a set does not remember which item came first, only which items exist. If you need the duplicates gone and the original order kept, a dictionary does the job instead, because a dictionary's keys can never repeat and it does remember insertion order:
$ >>> list(dict.fromkeys(tags))$ ['python', 'beginner', 'tutorial']The operations a set is actually for
A set is not just a list with duplicates removed. It carries its own arithmetic for comparing two collections at once, straight out of how you would describe sets on a maths whiteboard.
$ >>> admins = {"ada", "grace"}$ >>> editors = {"grace", "alan"}$ >>> admins | editors$ {'ada', 'grace', 'alan'}$ >>> admins & editors$ {'grace'}$ >>> admins - editors$ {'ada'}$ >>> admins ^ editors$ {'ada', 'alan'}Everyone in either set.
Only the people who are in both.
In the first set, and not in the second.
In exactly one of the two, never both.
admins & editors answers "who has both roles" in one expression, with no loop and no temporary list — which is usually why a set was the right choice before deduplication even came into it.
Testing membership without a loop
Membership testing is the reason sets exist at all. Checking whether a value is in a list means Python walks the list from the start until it finds it, or reaches the end. Checking a set is close to instant regardless of size, because a set is built, internally, for exactly this question.
$ >>> allowed = {"admin", "editor", "viewer"}$ >>> "editor" in allowed$ TrueKey takeaways
- 0, empty strings, empty collections, and None are all falsy. Everything else, including the string "False", is truthy.
- if x: and if x is not None: are different questions — use the second whenever an empty value is a real, valid answer you must not confuse with a missing one.
- == compares values; is compares identity. Use is only for None, and == for everything else.
- A set holds each value at most once, and set(some_list) is the fastest way to deduplicate — at the cost of losing the original order.
- Membership tests (in) are close to instant on a set and get slower the longer a list is. That speed is the reason sets exist.
Quick check
Answer these to unlock the next chapter — 3 of 4 to pass. You can retake it anytime.
Answer every question to check.
Make a free account to read on
Every chapter is free — an account is how your progress, XP, and streak follow you from your laptop to your phone, and how you show up on the leaderboard. No payment, no trial.