The str.partition(sep) method splits a string at the first occurrence of a specified separator and returns a 3-element tuple containing (head, sep, tail).
The Safe Unpacking Guarantee: Unlike str.split(sep, 1), which returns a 1-item list if the separator is missing and triggers an unpacking ValueError, partition() guarantees exactly three items every time. If the separator is not found, it returns (original_string, "", "").
The standard CPython signature for str.partition() is:
str.partition(sep)
| Parameter | Type | Default | Description |
|---|---|---|---|
sep |
str |
Required | The separator string to search for from left to right. Must be a non-empty string. Passing an empty string ("") raises a ValueError. |
tuple[str, str, str].
When partitioning a string, Python behaves deterministically based on whether sep exists inside the target:
sentence = "Python is powerful and versatile"
# 1. Separator is present: splits at first occurrence
head, sep, tail = sentence.partition("is")
print("Head: ", repr(head))
print("Sep: ", repr(sep))
print("Tail: ", repr(tail))
# 2. Separator is absent: returns (original, "", "")
missing_head, missing_sep, missing_tail = sentence.partition("Java")
print("\nWhen missing:")
print("Head: ", repr(missing_head))
print("Sep: ", repr(missing_sep))
print("Tail: ", repr(missing_tail))
Expected Output:
Head: 'Python '
Sep: 'is'
Tail: ' powerful and versatile'
When missing:
Head: 'Python is powerful and versatile'
Sep: ''
Tail: ''
Because the second element is strictly empty ("") when the separator is absent, verifying whether a partition succeeded requires only a simple boolean check: if sep: ....
In file parsers and network ingestion loops, developers often write code like k, v = line.split("=", 1). This idiom is fragile and prone to crashes:
line = "DATABASE_NAME" # Missing the '=' separator
# FLAWED: split() raises an unhandled exception
try:
k, v = line.split("=", 1)
except ValueError as e:
print("split() failed: ", e)
# ROBUST: partition() never raises ValueError on unpack
k, sep, v = line.partition("=")
print("partition() output:", k, "|", sep, "|", v)
Expected Output:
split() failed: not enough values to unpack (expected 2, got 1)
partition() output: DATABASE_NAME | |
| Feature | str.partition(sep) |
str.split(sep, 1) |
|---|---|---|
| Return Container | 3-tuple |
list (1 or 2 items) |
| Unpacking Safety | 100% safe (always 3 items) | Unsafe (fails if sep is absent) |
| Separator Retained? | Yes (at index 1) | No (discarded) |
| Absence Fallback | (s, "", "") |
[s] |
| Memory Overhead | Minimal (fixed-size tuple) | Slightly higher (dynamic list) |
While partition() splits at the first occurrence from the left, rpartition() splits at the last occurrence from the right. Note how the missing-separator fallback differs:
path = "var/log/nginx/access.log"
# 1. partition() isolates the root prefix
root, sep1, rest = path.partition("/")
print("partition(): ", (root, sep1, rest))
# 2. rpartition() isolates the final filename
directory, sep2, filename = path.rpartition("/")
print("rpartition(): ", (directory, sep2, filename))
# 3. Missing separator behavior difference:
raw = "standalone_word"
print("partition missing: ", raw.partition(":")) # ('standalone_word', '', '')
print("rpartition missing: ", raw.rpartition(":")) # ('', '', 'standalone_word')
Expected Output:
partition(): ('var', '/', 'log/nginx/access.log')
rpartition(): ('var/log/nginx', '/', 'access.log')
partition missing: ('standalone_word', '', '')
rpartition missing: ('', '', 'standalone_word')
Safely parsing configuration strings even when lines omit the delimiter or contain empty values:
def parse_config_setting(line: str, default_val: str = "true") -> tuple[str, str]:
# Guaranteed 3-tuple unpack
key, sep, val = line.partition("=")
key = key.strip()
val = val.strip() if sep else default_val
return key, val
print("With explicit value: ", parse_config_setting("ENABLE_CACHE = false"))
print("With boolean flag: ", parse_config_setting("VERBOSE_LOGGING"))
Expected Output:
With explicit value: ('ENABLE_CACHE', 'false')
With boolean flag: ('VERBOSE_LOGGING', 'true')
Decomposing URL strings into transport protocol and resource targets without regular expressions:
def extract_uri_scheme(uri: str) -> tuple[str, str]:
scheme, sep, remainder = uri.partition("://")
if not sep:
return "http", uri # Default to http if omitted
return scheme.lower(), remainder
url1 = "https://api.plus2net.com/v1/users"
url2 = "api.internal.local:8080"
print("URL 1:", extract_uri_scheme(url1))
print("URL 2:", extract_uri_scheme(url2))
Expected Output:
URL 1: ('https', 'api.plus2net.com/v1/users')
URL 2: ('http', 'api.internal.local:8080')
Separating local mailbox names from host domains with validation:
def parse_email_parts(email: str) -> tuple[str, str] | None:
mailbox, sep, domain = email.strip().partition("@")
if not sep or not mailbox or not domain or "@" in domain:
return None # Invalid structure
return mailbox, domain
valid_email = "developer@plus2net.com"
invalid_email = "malformed_user"
print("Valid email: ", parse_email_parts(valid_email))
print("Invalid email:", parse_email_parts(invalid_email))
Expected Output:
Valid email: ('developer', 'plus2net.com')
Invalid email: None
Passing an empty string "" to partition() raises an immediate exception:
# Raises ValueError: empty separator
"test".partition("")
Always ensure dynamic search strings are validated to be non-empty before partitioning.
partition() returns a tuple, not a list. Tuples are immutable; you cannot reassign items in place (e.g., result[0] = "new" raises TypeError: 'tuple' object does not support item assignment). If you need mutability, convert with list(result).
Below is a production-grade utility class, TuplePartitioner, demonstrating robust header extraction, query parameter splitting, and automated unit assertions:
class TuplePartitioner:
@staticmethod
def split_header(header_line: str) -> tuple[str, str]:
"""Extracts HTTP header name and value safely."""
name, sep, val = header_line.partition(":")
return name.strip(), val.strip()
@staticmethod
def split_path_query(url_path: str) -> tuple[str, str]:
"""Separates path endpoint from query string."""
path, sep, query = url_path.partition("?")
return path, query
@staticmethod
def has_delimiter(text: str, delimiter: str) -> bool:
"""Checks delimiter presence using partition tuple center."""
_, sep, _ = text.partition(delimiter)
return bool(sep)
# ==========================================
# SELF-CHECKING UNIT ASSERTIONS
# ==========================================
partitioner = TuplePartitioner()
# 1. Separator present unpack
h, s, t = "Alpha=Beta=Gamma".partition("=")
assert h == "Alpha"
assert s == "="
assert t == "Beta=Gamma"
# 2. Separator absent unpack (safe guarantee)
h2, s2, t2 = "PlainString".partition("=")
assert h2 == "PlainString"
assert s2 == ""
assert t2 == ""
# 3. HTTP Header Parsing
name, val = partitioner.split_header("Content-Type: application/json; charset=utf-8")
assert name == "Content-Type"
assert val == "application/json; charset=utf-8"
# 4. Path & Query Splitting
path, query = partitioner.split_path_query("/api/v1/search?term=python&limit=10")
assert path == "/api/v1/search"
assert query == "term=python&limit=10"
# 5. Delimiter presence check
assert partitioner.has_delimiter("USER=admin", "=") is True
assert partitioner.has_delimiter("USER_ADMIN", "=") is False
# 6. Empty separator ValueError validation
try:
"sample".partition("")
assert False, "Expected ValueError not raised"
except ValueError as e:
assert "empty separator" in str(e)
print("Header parsed: ", name, "->", val)
print("Path & query split:", path, "->", query)
print("All str.partition() unit assertions passed successfully!")
Open in Google Colab View on GitHub
Run all 3-tuple partition examples interactively, contrast partition() with split(..., 1), test rpartition() right-hand splitting, and parse HTTP headers in Google Colab.
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.