Chapter 09 of 24 | Python
Strings and text
A Python str is an immutable sequence of Unicode code points. Use quotes to create text, and f-strings to combine values with readable formatting.
language = "Python"
version = 3
print(f"{language} {version} is ready")
print("red,green,blue".split(","))
Common string operations
Strings support indexing, slicing, searching, replacing, splitting, joining, and trimming. Most methods return a new string because strings are immutable. strip removes leading and trailing whitespace; split divides text into a list; join combines an iterable of strings using a separator.
parts = ["learn", "by", "building"]
sentence = " ".join(parts)
cleaned = " report.txt ".strip()
has_suffix = cleaned.endswith(".txt")
Use in to test for a substring, find when you need its position or a “not found” result, and replace for literal substitution. For repeated string construction, collect pieces in a list and join once rather than assuming repeated concatenation has the cost you expect.
Bytes are not text
Text is encoded into bytes for files and networks. UTF-8 is a common encoding. Decoding bytes with the wrong encoding can fail or corrupt text; specify an encoding at boundaries, usually encoding="utf-8". A Python string's length counts code points, not necessarily user-perceived characters: a visible symbol may be composed of multiple code points.
text = "café"
encoded = text.encode("utf-8")
decoded = encoded.decode("utf-8")
print(len(text), len(encoded))
Formatting and injection risks
F-strings are convenient for display, but they are not a safe way to construct SQL, shell commands, or HTML from untrusted input. Use a database driver's parameterized queries, argument arrays for subprocesses, or a context-aware escaping/templating system. Escaping rules depend on the output context.
For machine-readable output, define delimiters, escaping, encoding, and newline behavior. A naive comma split is not a full CSV parser; fields may be quoted and contain commas. Use the standard csv module for CSV data.
Beginner-to-master progression
- Beginner: create strings, index, slice, and format them.
- Practitioner: distinguish text from bytes and declare encodings explicitly.
- Advanced: consider Unicode normalization, grapheme segmentation, locale, collation, and output-context security with a dedicated library and explicit policy.
Exercises
- Normalize whitespace in a sentence and count its words.
- Write and read UTF-8 text explicitly, including a non-ASCII character.
- Parse a CSV file with the standard library instead of splitting lines on commas.
- Explain why code-point count is not always the same as the number of characters a person sees.
Unicode normalization and comparisons
Unicode permits some visually equivalent text to be represented by different code-point sequences. The standard unicodedata module provides normalization forms such as NFC and NFD, but normalization is not a universal “clean text” operation. Select a form only when the protocol or application defines it. Case-insensitive comparison can require Unicode case folding rather than lowercasing; linguistic sorting depends on locale-aware collation rules.
import unicodedata
left = "é"
right = "e\u0301"
print(left == right) # may be False: different code-point sequences
print(unicodedata.normalize("NFC", left)
== unicodedata.normalize("NFC", right))
For user-visible character counting or cursor movement, use a library that understands grapheme clusters. A Python string's indexes are code-point indexes, not byte indexes or terminal column positions. Combining marks, emoji modifiers, and joined emoji sequences make the distinction visible.
Safe formatting and structured output
F-strings are appropriate for readable output within a trusted program. They do not automatically escape for HTML, SQL, a shell, or a URL. Use the receiving system's parameterized or escaping API. For example, a database query should use bound parameters; HTML should be produced by a template system configured for escaping.
When designing a text protocol, explicitly state encoding, newline convention, normalization, delimiters, escaping, and invalid-byte behavior. Avoid assuming that a string's visual appearance is a stable identifier. Security-sensitive identifiers may need a canonicalization and confusable-character policy.
Mastery checkpoint
- Normalize two canonically equivalent strings and explain when normalization should occur.
- Design a text protocol's encoding and malformed-input policy.
- Review code that inserts a string into SQL, HTML, and a shell command; select the correct safe API for each context.
- Explain why code-point indexing cannot correctly implement user-visible cursor movement.