Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsUse if not items: to run code when a Python list is empty, and if items: when it contains one or more values. Python treats an empty list as false and a non-empty list as true, so this is the conventional, readable approach.
items = []
if not items:
print("The list is empty")
else:
print("The list has items")
The idiomatic empty-list check
Python lets an if statement evaluate any object for truth. For built-in lists, truth is determined by the number of elements: [] is false, while a list with at least one element is true. The not operator reverses that result.
names = []
if not names:
print("No names were supplied")
This avoids an unnecessary length calculation in the source code and communicates the intent directly: proceed when the sequence has no items. PEP 8 recommends this direct sequence test.
Checking for a non-empty list
Use the same rule without not when the branch should run only if values are present.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
queue = ["email", "thumbnail"]
if queue:
print(f"Processing {len(queue)} jobs")
The condition is true for every non-empty list, regardless of the value types or whether the values themselves are false-like, such as 0, False or an empty string. The list’s length controls the list’s truth value.
What Python means by “empty”
Python’s truth-value rules define an object as false when its __bool__() method returns False or, when that method is absent, its __len__() method returns zero. Empty built-in sequences and collections, including lists, are therefore false.
examples = [[], [0], [False], [""]]
for value in examples:
print(bool(value))
# False
# True
# True
# True
Only the first list is empty. A list containing a false-like value still has one element and is therefore truthy.
When len(items) == 0 is the better expression
len(items) == 0 is correct and sometimes clearer when the numeric count is part of the decision or will be used immediately.
Recommended Free Tools
if len(records) == 0:
print("The import produced zero records")
if len(records) >= 100:
print("The batch is at least 100 records")
For a simple empty-versus-non-empty branch, prefer if not records:. Avoid making if len(records): or if not len(records): your default style; PEP 8 specifically favors testing the sequence itself.
Rank #2
For a normal list, both len(records) and truth testing are constant-time operations because a list stores its current length. The choice is primarily about expressing intent, not measurable speed.
Distinguish None from an empty list
None and [] are both false in a Boolean context, but they often represent different states. None can mean that no list was supplied, while an empty list can mean that a valid query returned zero results.
def describe(items):
if items is None:
return "No list was provided"
if not items:
return "A list was provided, but it is empty"
return f"The list has {len(items)} item(s)"
print(describe(None))
print(describe([]))
print(describe(["ready"]))
Use items is None for the absence check. Do not replace it with if not items when the two states must be handled differently. Conversely, if both None and an empty list should mean “nothing to process,” a single truth test may be appropriate:
if not items:
return []
Why is [] is not an emptiness test
The is operator tests object identity: whether two references point to the same object. The list literal [] creates a list object, so it will not normally be the very same object as your variable.
items = []
print(items is []) # False: different list objects
print(items == []) # True: equal contents
print(not items) # True: empty list
Use is only for singleton identity checks such as items is None. Use truth testing for emptiness. items == [] compares contents and works for a list, but it is less general and less idiomatic than not items for this purpose.
Choose the form that matches your intent
| Goal | Recommended code | Reason |
|---|---|---|
| Run code for an empty list | if not items: |
Concise, readable sequence truth test. |
| Run code for a non-empty list | if items: |
Directly expresses “has at least one item.” |
| Require a numeric count | if len(items) == 0: |
Makes the count comparison explicit. |
| Handle missing input separately | if items is None:, then elif not items: |
Separates absence from an empty list. |
| Compare list contents deliberately | items == [] |
Equality comparison, not a general truth test. |
| Check identity | Do not use items is [] |
Identity does not describe whether contents are empty. |
Practical patterns
Returning early from a function
def first_email(emails):
if not emails:
return None
return emails[0]
result = first_email([])
if result is None:
print("There is no email to send")
This guard prevents an IndexError from indexing an empty list and keeps the normal path uncluttered.
Skipping work in a loop
pending_batches = [[], ["a", "b"], []]
for batch in pending_batches:
if not batch:
continue
process_batch(batch)
The check is useful when a pipeline can produce empty batches and there is no work to perform for them.
Filtering empty results
responses = [["ok"], [], ["retry", "later"]]
non_empty = [response for response in responses if response]
print(non_empty)
# [['ok'], ['retry', 'later']]
Here the truth test intentionally keeps only lists containing at least one element.
Nested lists
Check the particular level whose contents matter. Testing the outer list does not tell you whether each inner list has values.
rows = [[], [1, 2], []]
if rows:
print("There are rows")
if any(rows):
print("At least one row is non-empty")
if all(rows):
print("Every row is non-empty")
rows is non-empty because it contains three inner lists. any(rows) checks whether at least one inner list is truthy, and all(rows) checks whether every inner list is truthy. An entirely empty outer list makes both any(rows) and all(rows) false and true respectively, following Python’s normal “all of an empty collection” rule; use the expression that matches your business meaning.
Common mistakes and fixes
Using if len(items): as a Boolean test
This works because zero is false and positive lengths are true, but it obscures the fact that items is a sequence. Replace it with if items: unless the length itself is needed.
Checking the wrong variable
items = load_items()
# Correct: test the loaded list
if not items:
print("Nothing loaded")
Make sure you are not checking a stale list, a source filename, or the result of a different operation. Naming intermediate values clearly helps prevent this error.
Assuming a list exists when a function can return None
If a function’s return contract permits None, decide whether that means “empty” or “invalid” and handle it explicitly. Otherwise, a broad if not result can silently combine two states that require different recovery actions.
Expecting element values to control list truth
[False], [0] and [None] are all non-empty lists. If you need to know whether any element is truthy, use any(items); if every element must be truthy, use all(items).
values = [0, None, ""]
if values:
print("The list has elements")
if not any(values):
print("None of the elements is truthy")
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Lists, other iterables and custom classes
The same syntax works for tuples, strings, dictionaries, sets and other objects that implement Python’s truth-value protocol. An empty tuple, string, dictionary or set is false. This makes if not sequence: broadly useful, but do not assume every iterable has a length.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Best Value
def has_values(value):
return bool(value)
print(has_values([])) # False
print(has_values((1, 2))) # True
print(has_values("")) # False
A generator is an important exception: generators do not provide a useful emptiness test without consuming them. Calling bool(generator) normally returns true because the generator object exists, even when it will yield no values. Convert it to a list when consumption is acceptable, or retrieve and inspect the next item with a sentinel when you must preserve streaming behavior.
Custom classes can define __bool__() or __len__(), so their truth behavior is controlled by the class author. A built-in list, however, always follows its element count.
Testing your empty-list branches
Include both boundary cases in automated tests, plus None when your API allows it.
def status(items):
if items is None:
return "missing"
if not items:
return "empty"
return "present"
assert status(None) == "missing"
assert status([]) == "empty"
assert status([0]) == "present"
The third assertion is useful because it proves that a list containing a false-like value is still considered present.
Or skip the browser setup
If your Python workflow also needs a clean image of a web page for documentation or test artifacts, ScreenshotNeo provides a single HTTP request rather than requiring you to configure a headless browser. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result.
Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
const data = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', data);
See the complete parameter list and response details in the ScreenshotNeo documentation. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients. Plans include 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Create a free ScreenshotNeo account to try it.
Quick Recap
Quick checklist
- Use
if not items:for the ordinary empty-list branch. - Use
if items:for the ordinary non-empty branch. - Use
len(items) == 0when an explicit count comparison improves clarity. - Check
items is Nonebefore the emptiness test when missing and empty have different meanings. - Never use
items is []to test contents. - Remember that a list containing false-like values is still non-empty.
- Test empty, non-empty and, where relevant,
Nonecases.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




