Today's outcomes
- Index and slice strings safely.
- Use strip, split, join, and replacement.
- Explain why methods return new strings.
Before you start: Complete Day 11 and its practical challenge.
Understand the concept
Strings are immutable Unicode sequences
A Python string contains Unicode code points. Indexing returns a one-character string for one code point, and slicing returns another string. Its characters cannot be replaced by item assignment. Methods such as replace and strip produce new strings, so keep the returned value when you need the transformation.
The length of a string counts code points, not bytes, display columns, or every user's idea of a visible character. An accented character can use one composed code point or a letter plus a combining mark. This course's simple ASCII task labels avoid those complexities in their acceptance fixtures, but real text processing needs a clear policy.
The stop boundary of a slice is excluded. An index outside a string raises IndexError, while an oversized slice is clipped. Empty strings therefore support slices but not a required first-character lookup. Check the actual operation before choosing an emptiness guard.
Strip, split, and join solve different tasks
strip() removes leading and trailing whitespace. It does not remove whitespace inside the string. With an explicit argument, strip treats that argument as a set of characters to remove at the edges, not an exact prefix. Use removeprefix or removesuffix when a literal boundary substring is intended.
split() without an argument groups whitespace-separated text and ignores leading/trailing whitespace runs. split(',') uses that exact separator and can retain empty fields. Those contracts differ: an empty CSV-like field may be evidence of missing data rather than something to delete.
separator.join(parts) builds one string from a sequence of strings. A separator belongs between items rather than after every item. Every item must be a string; join does not automatically convert integers. Separating text preparation from formatting makes these requirements easier to test.
Define what a cleaning rule may change
A topic label might ignore surrounding whitespace and case. A person's display name should often preserve their chosen spelling. An account ID may require exact case. A password should not be normalized without a specific contract. “Clean everything” is not a sufficient field-level policy.
Preserve an original value when transformed text is used as a comparison key. Several originals can produce one key; that can be useful for search and dangerous for unique identities. See the linked Unicode article in the source notes for deeper normalization and collision examples.
Worked example
raw = " Lists, Functions,, Dictionaries "
fields = raw.strip().split(",")
topics = []
for field in fields:
cleaned = field.strip().casefold()
if cleaned:
topics.append(cleaned)
report = " | ".join(topics)
print("Original:", repr(raw))
print("Fields:", fields)
print("Report:", report)
assert topics == ["lists", "functions", "dictionaries"]
assert report == "lists | functions | dictionaries"
assert raw.startswith(" ")
| Stage | Result | Policy |
|---|---|---|
| Trim outer source | No outer spaces | Ignore surrounding whitespace |
| Split by comma | Includes one empty field | Preserve separators during interpretation |
| Trim and casefold each field | Lower comparison labels | Ignore case for topic labels |
| Filter empty normalized fields | Three topics | This label-list contract excludes blanks |
| Join for display | lists | functions | dictionaries | Put separators between labels |
The literal vertical bars in the displayed report are separators, not set-union operators. Context determines the meaning of the character. The original source is unchanged because the transformations created new strings and lists.
Guided practice
- Predict: compare
"a,,b".split(',')with" a b ".split(). The first retains an empty comma-separated field; the second produces two whitespace-separated words. - Modify: preserve original case for display while using casefolded keys only for duplicate detection. Explain which collection stores display labels and which stores membership keys.
- Reconstruct: remove a literal prefix
"topic:"from a label using removeprefix, then trim surrounding whitespace. Compare that with strip using the same characters and explain why the latter can remove unintended edge letters.
Before using a string method, write one expected transformation and one value that should remain unchanged. This discourages a broad rule that looks convenient but damages valid data.
Daily challenge
Implement clean_topic_list(text). Accept comma-separated topic labels. Trim each field, exclude blanks, deduplicate case-insensitively, and preserve the first cleaned spelling and original order. Return a list of display labels. Do not sort it and do not change interior spaces.
| Input | Expected result |
|---|---|
" Lists, functions,LISTS, , Strings " |
['Lists', 'functions', 'Strings'] |
"" |
[] |
" Data Science ,data science " |
['Data Science'] |
"A B,A B" |
['A B', 'A B'] |
The final case demonstrates the exact policy: surrounding whitespace is ignored, while internal spacing remains significant. A different application may collapse internal runs, but this contract does not.
Reference solution
Compare after attempting the challenge
def clean_topic_list(text):
result = []
seen = set()
for field in text.split(","):
display = field.strip()
key = display.casefold()
if not display or key in seen:
continue
seen.add(key)
result.append(display)
return result
assert clean_topic_list(" Lists, functions,LISTS, , Strings ") == ["Lists", "functions", "Strings"]
assert clean_topic_list("") == []
assert clean_topic_list(" Data Science ,data science ") == ["Data Science"]
assert clean_topic_list("A B,A B") == ["A B", "A B"]
print("Text policy passed")
The list preserves order and display spelling, while the set handles comparison membership. One container would not express both requirements as clearly. This is a practical example of choosing data structures for their roles rather than personal preference.
Debug and explain
If a transformation has no visible effect, check whether you ignored the returned string. If blank fields disappear unexpectedly, check which split form you used. If distinct IDs merge, inspect the equality policy before blaming the set or dictionary.
Explain why the final two labels in the last case remain distinct, why deduplication retains the first spelling, and why this function is not a CSV parser. Quoted commas require a CSV-aware parser, not this deliberately simple separator contract.
Review and next step
This second checkpoint connects functions, lists, tuples, dictionaries, sets, and strings. Rebuild clean_topic_list and explain each container's purpose. Day 13 adds escapes and formatted reports while keeping original data separate from its presentation.
Sources and verification
Original teaching examples checked with Python 3.12.14. Library behavior reviewed against these primary references on October 3, 2026. Day 26's examples also use Beautiful Soup 4.14.3.
Check your understanding
Five questions, 20 points each. Pass at 85% or above, which requires all five correct. Feedback explains each answer; revise the lesson and retry when needed.
Review your practical work
Check these statements after running your own challenge. This is your self-review; the website does not execute or assess your Python code.
Pass the knowledge check and finish the practical self-review to save completion.