Of course! Let's dive into Python's string formatting using the operator, often called "old-style" or "printf-style" formatting.

This method was inherited from C's printf function and was the primary way to format strings in Python for a long time. While newer methods like str.format() and f-strings are now more common, it's still important to recognize this syntax as you'll encounter it in older codebases.
The Basic Idea
The operator uses a "format string" on the left and a tuple of values on the right. The format string contains placeholders, which are marked by the character. The operator replaces these placeholders with the values from the tuple.
The Placeholders: Types
The character immediately following the in the placeholder specifies the type of data that should be inserted.
| Code | Type | Example |
|---|---|---|
%s |
String | Formats any Python object using str() |
%d |
Integer | Formats a decimal integer |
%f |
Floating Point | Formats a floating-point number |
%x |
Hexadecimal | Formats an integer as a lowercase hexadecimal number |
%X |
Hexadecimal | Formats an integer as an uppercase hexadecimal number |
| Literal '%' | A literal percent sign is required in the output |
Examples in Detail
Basic String (%s)
This is the most flexible placeholder. It can take almost any Python object and convert it to a string.

name = "Alice" age = 30 # The %s placeholder will be replaced by the value of 'name' greeting = "Hello, %s" % name print(greeting) # Output: Hello, Alice # You can use multiple placeholders by providing a tuple of values # The order matters! info = "Name: %s, Age: %s" % (name, age) print(info) # Output: Name: Alice, Age: 30
Integer (%d)
This is specifically for whole numbers.
items = 5 message = "You have %d items in your cart." % items print(message) # Output: You have 5 items in your cart.
Floating-Point Number (%f)
This is for numbers with decimal points. You can also specify the precision (number of decimal places) by adding a .precision modifier.
price = 99.95 # Default precision is usually 6 decimal places msg1 = "The price is %f." % price print(msg1) # Output: The price is 99.950000. # Format to 2 decimal places (like for currency) msg2 = "The price is %.2f." % price print(msg2) # Output: The price is 99.95.
Combining Different Types
You can mix and match different placeholders in a single string.
product = "Laptop" quantity = 2 unit_price = 1200.50 receipt_line = "Product: %s, Qty: %d, Total: $%.2f" % (product, quantity, unit_price) print(receipt_line) # Output: Product: Laptop, Qty: 2, Total: $2401.00
Special Cases
Literal Percent Sign ()
If you need to include a literal in your string, you must escape it by using .

progress = 75 # The %% is replaced by a single '%' character status = "Download complete: %d%%" % progress print(status) # Output: Download complete: 75%
Padding and Alignment
You can add numbers before the type specifier to control padding and alignment.
%5d: Pad the integer with spaces to a total width of 5.%-5d: Pad with spaces to a width of 5, but left-align the number.%.5f: Pad the float with zeros to 5 decimal places.
num1 = 42
num2 = 100
# Right-aligned in a space of 5 characters
print("Number 1: %5d" % num1)
# Output: Number 1: 42
# Left-aligned in a space of 5 characters
print("Number 2: %-5d" % num2)
# Output: Number 2: 100
# Padded to 5 decimal places
pi = 3.14159
print("Pi: %.5f" % pi)
# Output: Pi: 3.14159
Key Points and Comparison to Modern Methods
| Feature | (Old-Style) | str.format() (New-Style) |
f-strings (Literal) |
|---|---|---|---|
| Syntax | "Hello %s" % "World" |
"Hello {}".format("World") |
f"Hello {World}" |
| Readability | Can become cluttered with many variables. | Very clear, uses named or indexed placeholders. | Extremely readable, code is embedded in the string. |
| Flexibility | Limited. Can be hard to format complex objects. | Very flexible. Supports attribute/index access and advanced formatting specs. | Very flexible. Allows for full expressions inside . |
| Performance | Fast, but generally slower than f-strings. | Slower than f-strings. | Fastest. The string is evaluated at runtime, which is highly optimized. |
| Recommendation | Avoid in new code. Use for maintaining legacy code. | Good, but f-strings are now preferred for new code. | Recommended for all new Python 3.6+ code. |
Summary
The operator is a powerful and concise way to format strings, especially for simple cases. However, for modern Python development, f-strings (since Python 3.6) are the recommended approach due to their superior readability and performance. str.format() is a great middle-ground and is essential for compatibility with older Python versions (3.5 and below).
You should be comfortable reading formatting, but default to using f-strings for your own code.
