String formatting with f-strings, format(), and template strings. Translation tables for character mapping. String templates for safer substitution. The textwrap module for formatting paragraphs. string module constants and utilities. These tools make string handling powerful and efficient.
This lesson explores advanced string techniques. You will learn to format strings in multiple ways, create translation tables, use string templates, and leverage the full power of Python’s string capabilities.
🕯️ Magic Note
Strings in Python are immutable. Every operation creates a new string. This is important for performance when manipulating large strings. For heavy string building, use join() or io.StringIO instead of concatenation in loops.
Python
# Positional arguments
print(“Hello, {}! Your score is {}”.format(“Ali”, 95))
print(“{0} has {1} apples, and {0} has {2} oranges”.format(“Ali”, 5, 3))
# Keyword arguments
print(“Name: {name}, Age: {age}”.format(name=”Feloriya”, age=25))
# Mixed positional and keyword
print(“{0} is {age} years old”.format(“Ali”, age=30))
# Format specifiers (alignment, width, precision)
print(“{:>10}”.format(“right”)) # ‘ right’
print(“{:<10}”.format(“left”)) # ‘left ‘
print(“{:^10}”.format(“center”)) # ‘ center ‘
print(“{:*^20}”.format(“stars”)) # ‘*******stars*******’
# Number formatting
print(“{:.2f}”.format(3.14159)) # ‘3.14’
print(“{:,.2f}”.format(1234567.89)) # ‘1,234,567.89’
print(“{:+.2f}”.format(3.14159)) # ‘+3.14’
print(“{:.2%}”.format(0.856)) # ‘85.60%’
# Binary, octal, hexadecimal
print(“{:b}”.format(42)) # ‘101010’
print(“{:o}”.format(42)) # ’52’
print(“{:x}”.format(42)) # ‘2a’
print(“{:#x}”.format(42)) # ‘0x2a’ (with prefix)
# Formatting with dictionaries
data = {“name”: “Sara”, “score”: 95}
print(“{name} scored {score} points”.format(**data))
Python
from string import Template
# Basic template
t = Template(“Hello, $name! You have $count messages.”)
print(t.substitute(name=”Ali”, count=5))
# Hello, Ali! You have 5 messages.
# Using dictionaries
data = {“name”: “Sara”, “count”: 3}
print(t.substitute(data))
# safe_substitute (no KeyError if variable missing)
print(t.safe_substitute(name=”Reza”)) # Hello, Reza! You have $count messages.
# Changing delimiter
class MyTemplate(Template):
delimiter = ‘#’
t2 = MyTemplate(“Welcome #user, your email is #email”)
print(t2.substitute(user=”Ali”, email=”ali@example.com”))
🕯️ Magic Note
Templates are safer than f-strings or format() when dealing with user input because they do not evaluate expressions. They only substitute variables. This prevents injection attacks in certain contexts.
Python
import string
print(f”ASCII letters: {string.ascii_letters}”)
print(f”Lowercase: {string.ascii_lowercase}”)
print(f”Uppercase: {string.ascii_uppercase}”)
print(f”Digits: {string.digits}”)
print(f”Hex digits: {string.hexdigits}”)
print(f”Oct digits: {string.octdigits}”)
print(f”Punctuation: {string.punctuation}”)
print(f”Whitespace: {repr(string.whitespace)}”)
print(f”Printable: {string.printable}”)
# Practical use: generate random password
import secrets
alphabet = string.ascii_letters + string.digits
password = “”.join(secrets.choice(alphabet) for _ in range(12))
print(f”Random password: {password}”)
# Remove punctuation from text
text = “Hello, world! How are you?”
clean = text.translate(str.maketrans(“”, “”, string.punctuation))
print(f”Without punctuation: {clean}”)
Python
# Simple character replacement
trans = str.maketrans(“aeiou”, “12345”)
text = “hello world”
print(text.translate(trans)) # ‘h2ll4 w4rld’
# Removing characters
trans = str.maketrans(“”, “”, string.punctuation)
text = “Hello, World!”
print(text.translate(trans)) # ‘Hello World’
# Combining replacement and deletion
trans = str.maketrans(“aeiou”, “AEIOU”, “!@#”)
text = “hello! world@”
print(text.translate(trans)) # ‘hEllO wOrld’
# Practical: normalize text for slugs (URLs)
def slugify(text):
text = text.lower()
trans = str.maketrans(” “, “-“, string.punctuation)
return text.translate(trans)
print(slugify(“My Amazing Article!”)) # ‘my-amazing-article’
🕯️ Magic Note
translate() is much faster than replace() or looping through strings, especially for large texts. It is implemented in C and operates on the entire string at once.
Python
import textwrap
long_text = “This is a very long sentence that needs to be wrapped to a specific width. It contains multiple words that should be broken into lines of reasonable length.”
# Wrap text to 50 characters
wrapped = textwrap.wrap(long_text, width=50)
for line in wrapped:
print(line)
# Fill text (wrap and join with newlines)
filled = textwrap.fill(long_text, width=50)
print(filled)
# Shorten text with placeholder
shortened = textwrap.shorten(long_text, width=50, placeholder=”…”)
print(shortened)
# Indent text
indented = textwrap.indent(long_text, ” “)
print(indented)
# Dedent (remove common indentation)
dedented = textwrap.dedent(“””
This text
has inconsistent
indentation
“””)
print(repr(dedented))
# Custom wrapper settings
wrapper = textwrap.TextWrapper(width=40, initial_indent=”* “, subsequent_indent=” “)
print(wrapper.fill(long_text))
| Prefix | Meaning | Example |
|---|---|---|
| r | Raw string (no escape sequences) | r”C:\Users\name” |
| f | Formatted string (f-string) | f”Hello {name}” |
| b | Bytes literal (for binary data) | b”Hello” |
| u | Unicode string (default in Python 3) | u”Hello” |
| fr | Raw formatted string (combined) | fr”Value: {x}\n” |
Python
# Raw strings (ignore escape sequences)
print(“C:\\Users\\Ali”) # C:\Users\Ali
print(r”C:\Users\Ali”) # C:\Users\Ali (no escaping needed)
# Bytes strings (for binary data)
b = b”Hello”
print(type(b)) # <class ‘bytes’>
print(b[0]) # 72 (byte value, not a character)
print(b.hex()) # ‘48656c6c6f’
print(bytes.fromhex(“48656c6c6f”).decode()) # ‘Hello’
# Combined raw f-string
path = r”C:\Users\{name}\Documents”
name = “Ali”
print(f”{path}”) # C:\Users\{name}\Documents (not evaluated)
print(fr”C:\Users\{name}\Documents”) # C:\Users\Ali\Documents
Python
text = ” Hello World “
# Remove prefix/suffix (Python 3.9+)
url = “https://example.com”
print(url.removeprefix(“https://”)) # ‘example.com’
print(“file.txt”.removesuffix(“.txt”)) # ‘file’
# Check start/end with multiple options
filename = “image.jpg”
if filename.endswith((“.jpg”, “.png”, “.gif”)):
print(“Image file”)
# center, ljust, rjust for alignment
print(“Title”.center(20, “*”)) # ‘*******Title********’
print(“Left”.ljust(10, “-“)) # ‘Left——‘
print(“Right”.rjust(10, “-“)) # ‘—–Right’
# zfill: pad with zeros
print(“42”.zfill(5)) # ‘00042’
print(“-42”.zfill(5)) # ‘-0042’
# expandtabs: convert tabs to spaces
print(“a\tb\tc”.expandtabs(4)) # ‘a b c’
# isprintable: check if all characters are printable
print(“Hello”.isprintable()) # True
print(“Hello\n”.isprintable()) # False
Python
import re
import string
import textwrap
def clean_text(text):
“””Clean and normalize text for display.”””
# Convert to lowercase
text = text.lower()
# Remove punctuation (but keep spaces)
trans = str.maketrans(“”, “”, string.punctuation)
text = text.translate(trans)
# Remove extra whitespace
text = ” “.join(text.split())
return text
def truncate_with_ellipsis(text, max_length=100):
“””Truncate text to max_length without cutting words.”””
if len(text) <= max_length:
return text
truncated = text[:max_length]
last_space = truncated.rfind(” “)
if last_space > 0:
truncated = truncated[:last_space]
return truncated + “…”
def format_paragraph(text, width=70, indent=0):
“””Format text as a wrapped paragraph with indentation.”””
wrapper = textwrap.TextWrapper(
width=width,
initial_indent=” ” * indent,
subsequent_indent=” ” * indent
)
return wrapper.fill(text)
def slugify(text):
“””Convert text to URL-friendly slug.”””
text = text.lower()
text = re.sub(r”[^\w\s-]”, “”, text) # Remove special chars
text = re.sub(r”[-\s]+”, “-“, text) # Replace spaces/hyphens with single hyphen
return text.strip(“-“)
# Example usage
raw_text = ” Hello, World! This is a VERY long sentence that needs to be cleaned and formatted. “
print(f”Original: {raw_text}”)
print(f”Cleaned: {clean_text(raw_text)}”)
print(f”Truncated: {truncate_with_ellipsis(raw_text, 30)}”)
print(f”Slug: {slugify(raw_text)}”)
print(f”Formatted:\n{format_paragraph(raw_text, width=40, indent=2)}”)
- Forgetting that strings are immutable (creating new strings repeatedly in loops is slow)
- Not using raw strings for regex patterns or Windows paths
- Using string concatenation in loops instead of .join()
- Assuming translate() works without creating a translation table
- Mixing bytes and strings (TypeError)
- Write a function that removes all punctuation from a string using translate().
- What is the difference between Template.substitute() and safe_substitute()?
- Write a function that wraps text to 80 characters and indents the first line by 4 spaces.
- How do you convert a string to a URL-friendly slug?
- What are the advantages of using textwrap.dedent() for multi-line strings?
- When would you use str.maketrans() and translate() instead of replace()?
⚡ Whisper
Strings are more than quoted text. They are messages, data, code, art. Python gives you tools to shape them. format() for precision.
Template for safety. maketrans() for speed. textwrap for beauty. string constants for convenience. Each tool has its purpose. Learn them all. The raw string prefix r for paths and regex. The bytes prefix b for binary data. The f-string for clarity. Translate for efficiency. Wrap for readability. Dedent for clean multi-line strings. Master these, and you master text. Logs become readable. Reports become beautiful. APIs become clear. The string is the universal container. Fill it wisely.