036. Join() Method
Assemble sequences into strings efficiently
036. Join() Method
RAM Manager: Assembling Output Lines
Aryan’s RAM manager collects process data as lists and needs to output it as formatted lines. He’s building three assembler functions:
- A CSV exporter (for piping to other tools)
- A terminal table row (column display)
- A breadcrumb path builder (for showing /proc paths)
# What he has
fields = ["chrome", "812", "544MB", "6.8%"]
# Bad (O(n²), trailing separator bug):
line = ""
for i, f in enumerate(fields):
line += f
if i < len(fields) - 1:
line += ","
# → "chrome,812,544MB,6.8%" (works but wrong way)
# Right way
line = ",".join(fields)The sentence function has a subtle trailing-space bug that would corrupt his output. Fix all three.
💡 Fun fact: String concatenation in a loop (result += item) is O(n²) because each += creates a new string and copies all previous content — just like adding a brick to a wall by rebuilding the entire wall each time. str.join() pre-calculates the final length and allocates once, making it O(n). This difference becomes noticeable around 10,000+ strings.
⚠️ Watch out: join() requires all items to be strings — ",".join([1, 2, 3]) raises a TypeError. Beginners are surprised by this because print(1, 2, 3) auto-converts numbers, but join() does not. Always convert with str(x) or a list comprehension: ",".join(str(x) for x in numbers).
🤔 Think about it: "".join(["h","e","l","l","o"]) gives "hello". What does list("hello") give you? And if those two operations are inverses, why doesn’t Python just let you call "hello"[:] to get a list of characters like you can with a list slice?
Learning objectives
- Use sep.join(list) to assemble strings
- Understand join() is the inverse of split()
- Prefer join() over string concatenation in loops
Key concepts
- join()
- string assembly
- efficiency
Try it
Concept detail
sep.join(iterable) is the inverse of split(). It inserts sep between each item.
ALL items must be strings — join() does not auto-convert numbers: “,”.join([1, 2, 3]) → TypeError! “,”.join([str(x) for x in [1, 2, 3]]) → “1,2,3”
Performance: join() is O(n), loop concatenation is O(n²). Why? join() pre-calculates total length, then allocates one string. Each += in a loop allocates a new string and copies all previous content. For 1000 items: join does 1 allocation, loop does 1000 with increasing copy sizes.
Common patterns: “,”.join(fields) → CSV line “ “.join(words) → sentence “\n”.join(lines) → multi-line text “/”.join(path_parts) → filesystem path “”.join(chars) → reassemble character list into string
Edge cases: “x”.join([]) → “” (empty iterable → empty string) “x”.join([“a”]) → “a” (single item → no separator)
Solution
def csv_line(fields):
return ",".join(fields)
def sentence(words):
return " ".join(words)
def breadcrumb(parts):
return " > ".join(parts)Tests
def test_csv_line():
assert csv_line(["Alice", "30", "Engineer"]) == "Alice,30,Engineer"
def test_csv_single():
assert csv_line(["only"]) == "only"
def test_csv_empty():
assert csv_line([]) == ""
def test_sentence():
assert sentence(["hello", "world"]) == "hello world"
def test_sentence_no_trailing_space():
result = sentence(["a", "b"])
assert result == "a b", f"Got {repr(result)} — trailing space detected"
def test_breadcrumb():
assert breadcrumb(["Home", "Products", "Laptop"]) == "Home > Products > Laptop"
def test_breadcrumb_single():
assert breadcrumb(["Home"]) == "Home"