The set.isdisjoint(other) method returns True if two collections have no elements in common (a null intersection with zero shared elements). If they share one or more elements, it returns False.
Early-Exit Short-Circuiting: Unlike calculating len(A.intersection(B)) == 0 or not (A & B), which construct an intermediate set in memory, isdisjoint() iterates through elements and terminates immediately upon discovering the very first collision, delivering optimal O(1) best-case runtime.
The standard CPython signature for set.isdisjoint() is defined as:
set_instance.isdisjoint(other)
| Component | Type | Required? | Behavior & Description |
|---|---|---|---|
other |
Iterable[Hashable] |
Yes (exactly one) | Any iterable collection (set, list, tuple, dictionary, or generator) to evaluate against. |
| Return Value | bool |
— | Returns True if intersection is empty; returns False if at least one shared element exists. |
| Best-Case Time | O(1) | — | Short-circuits instantly when the first element checked exists in both sets. |
| Worst-Case Time | O(min(len(A), len(B))) | — | When collections are completely disjoint, CPython iterates over the smaller container. |
| Auxiliary Space | O(1) | — | Zero memory allocations; tests membership directly in existing hash tables. |
Understanding disjoint status involves two scenarios: collections that overlap (returning False) and collections that share zero elements (returning True).
When sets share one or more members, isdisjoint() evaluates to False:
A = {'x', 'y', 'z'}
B = {'x', 'b', 'c'}
# 'x' is shared between both sets
overlap_check = A.isdisjoint(B)
print("Are sets A and B disjoint?", overlap_check)
Output:
Are sets A and B disjoint? False
When sets share zero elements, isdisjoint() confirms mutual exclusivity by returning True:
A = {'x', 'y', 'z'}
B = {'a', 'b', 'c'}
disjoint_check = A.isdisjoint(B)
print("Are sets A and B disjoint?", disjoint_check)
Output:
Are sets A and B disjoint? True
Like other set inspection methods, isdisjoint() accepts any iterable. However, passing strings directly can cause subtle bugs due to character-level iteration.
You can check a set directly against a standard Python list without converting the list to a set first:
allowed_ports = {80, 443, 8080}
blocked_list = [21, 22, 23, 25]
print("Ports disjoint from blocked list:", allowed_ports.isdisjoint(blocked_list))
Output:
Ports disjoint from blocked list: True
Passing a raw string unpacks each individual character into a separate token:
target_set = {'x', 'y', 'z'}
name_str = 'Alex' # Iterates through 'A', 'l', 'e', 'x'
# 'x' matches target_set → returns False!
print("String input check:", target_set.isdisjoint(name_str))
# To test entire words, always enclose the string in a list or set:
roles = {"admin", "editor"}
candidate = "guest"
print("Word-level check: ", roles.isdisjoint([candidate]))
Output:
String input check: False
Word-level check: True
Many developers check for shared elements using intersection idioms such as not (A & B) or len(A.intersection(B)) == 0. Here is why isdisjoint() is significantly more efficient:
| Technique | Short-Circuit? | Memory Allocated | Best-Case Time | Worst-Case Time |
|---|---|---|---|---|
A.isdisjoint(B) |
Yes (→ instant exit) | O(1) zero allocation | O(1) | O(min(len(A), len(B))) |
not (A & B) |
No (builds full set) | O(k) new set | O(len(A)) | O(len(A)) |
len(A.intersection(B)) == 0 |
No (builds full set) | O(k) new set | O(min(len(A), len(B))) | O(min(len(A), len(B))) |
# Huge set with a collision right at the beginning
huge_set_a = set(range(1_000_000))
quick_candidate = [0, 2_000_000, 3_000_000]
# isdisjoint checks 0 first, detects match, exits immediately in microseconds:
has_no_collision = huge_set_a.isdisjoint(quick_candidate)
print("Has no collision:", has_no_collision)
Output:
Has no collision: False
In financial and enterprise systems, regulations require that employees holding certain sensitive duties cannot hold conflicting approval permissions:
def validate_role_compliance(user_roles: set[str], incompatible_matrix: dict[str, set[str]]) -> bool:
for role, prohibited in incompatible_matrix.items():
if role in user_roles:
# User cannot hold any prohibited conflicting roles
if not user_roles.isdisjoint(prohibited):
return False
return True
conflict_rules = {
"invoice_creator": {"invoice_approver", "payment_dispatcher"},
"code_author": {"production_deployer"}
}
valid_account = {"invoice_creator", "report_viewer"}
invalid_account = {"invoice_creator", "payment_dispatcher"}
print("Valid account compliant:", validate_role_compliance(valid_account, conflict_rules))
print("Invalid account compliant:", validate_role_compliance(invalid_account, conflict_rules))
Output:
Valid account compliant: True
Invalid account compliant: False
Prevent user input or API parameter names from clashing with reserved system keywords:
RESERVED_ROUTES = {"admin", "api", "login", "logout", "billing", "healthz"}
def is_valid_tenant_subdomains(requested_aliases: list[str]) -> bool:
return RESERVED_ROUTES.isdisjoint(requested_aliases)
print("Candidate 1 ('blog', 'shop'):", is_valid_tenant_subdomains(["blog", "shop"]))
print("Candidate 2 ('admin', 'portal'):", is_valid_tenant_subdomains(["admin", "portal"]))
Output:
Candidate 1 ('blog', 'shop'): True
Candidate 2 ('admin', 'portal'): False
set().isdisjoint(anything) is always True, even when compared against another empty set:
print(set().isdisjoint({1, 2})) # True
print(set().isdisjoint(set())) # True (empty set intersection is empty)
data_set = {10, 20}
dict_map = {"a": 10, "b": 20}
# Evaluates against {'a', 'b'}, NOT {10, 20} → returns True!
print(data_set.isdisjoint(dict_map)) # True
print(data_set.isdisjoint(dict_map.values())) # False
Validate your understanding of isdisjoint() by running these self-verifying test assertions:
# Test 1: Fundamental boolean outcomes
s1 = {1, 2, 3}
assert s1.isdisjoint({4, 5, 6}) is True
assert s1.isdisjoint({3, 4, 5}) is False
# Test 2: Heterogeneous iterables
assert s1.isdisjoint([10, 20]) is True
assert s1.isdisjoint((2, 20)) is False
# Test 3: Empty set invariants
assert set().isdisjoint(s1) is True
assert set().isdisjoint(set()) is True
# Test 4: String character splitting vs list
letters = {'a', 'b'}
assert letters.isdisjoint("apple") is False # 'a' collides
assert letters.isdisjoint(["apple"]) is True # "apple" != 'a' or 'b'
print("All set.isdisjoint assertions passed successfully!")
Output:
All set.isdisjoint assertions passed successfully!
Deepen your skills with live interactive examples, short-circuit timing benchmarks, and security role compliance drills in our companion notebook:
Explore interactive code cells, benchmark isdisjoint() against intermediate set allocations, and solve role-compliance puzzle exercises.
Tests whether every element of the calling set is contained within another collection.
Tests whether the calling set contains every element of another collection.
Computes the set of common elements, returning a new set object.
Computes elements unique to the calling set, excluding items found in other iterables.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.