Quick answer: Python’s percent-style string formatting uses conversion markers such as %s and values supplied after the operator. Match the number and shape of arguments to the placeholders, escape literal percent signs as %%, and consider f-strings or str.format for new code.

%s is a placeholder used by Python’s old-style percent string formatting. The text on the left contains placeholders, and the value on the right side of the % operator supplies what should appear in those positions.
This style is still common in older code, logging examples, tutorials, and libraries that predate f-strings. For new application code, f-strings are usually easier to read, but understanding %s helps when maintaining existing projects.
The official Python printf-style string formatting documentation defines %s, mapping keys, width, precision, and literal percent signs.
Format One Value With %s
Use one %s placeholder when one value should be inserted into a string. Python converts the value with str().
name = "Maya"
message = "Hello, %s!" % name
print(message)
The % operator is part of the expression. The string on the left is the format template, and the value on the right fills the placeholder.
This pattern is compact, but it can become hard to read as the number of placeholders grows. Keep simple one-value formatting simple, and switch to a clearer style when the text becomes complex.
Use A Tuple For Multiple Placeholders
When the format string has more than one placeholder, pass a tuple on the right side. The tuple order must match the placeholder order.
template = "%s scored %s points"
text = template % ("Nora", 42)
print(text)
The second value is an integer, but %s converts it to string form. If you need numeric formatting, use placeholders such as %d or modern formatting tools with explicit numeric rules.
A common bug is forgetting the tuple for multiple placeholders. If the placeholder count and supplied values do not match, Python raises a formatting error.

Use Mapping Keys For Named Data
Old-style formatting can read values from a dictionary by using mapping keys inside the placeholder.
profile = {"name": "Iris", "role": "admin"}
line = "%(name)s has the %(role)s role" % profile
print(line)
Mapping keys make long format strings easier to maintain because the text does not depend on tuple order.
This style is common in older localization files and configuration templates. For new code, str.format() or f-strings often provide a more readable equivalent.
Control Width And Precision
%s supports width and precision. Width pads the output, while precision limits how many characters are shown.
items = ["alpha", "beta", "gamma"]
for item in items:
print("|%10s|" % item)
print("%.5s" % "documentation")
The width example right-aligns each item inside a ten-character space. The precision example keeps only the first five characters.
These controls can be useful for simple console tables, but they are limited compared with modern formatting. For aligned output in new code, f-strings with format specifications are often clearer.
Print A Literal Percent Sign
Because % starts a formatting placeholder, a literal percent sign must be written as %%.
done = 85
status = "Progress: %s%% complete" % done
print(status)
The first percent sequence, %s, receives the value. The second sequence, %%, becomes a single percent sign in the output.
This detail is easy to miss in progress messages, reports, and percentage labels. If the string contains a percent sign and also uses old-style formatting, check it carefully.

Compare %s With Modern Formatting
The same output can be written with old-style formatting, str.format(), or an f-string.
name = "Sam"
count = 3
old_style = "%s has %s tasks" % (name, count)
method_style = "{} has {} tasks".format(name, count)
f_string = f"{name} has {count} tasks"
print(old_style)
print(method_style)
print(f_string)
F-strings are usually the best default in modern Python because the expressions appear next to the surrounding text. str.format() is still useful for reusable templates and advanced format specifications.
Use %s when you are maintaining old code, matching an existing codebase style, or working with a library that expects percent-style templates. Otherwise, prefer f-strings for readability.
One place where percent formatting still appears often is logging. The standard logging package accepts a message and separate arguments, then formats the message only if the log record is emitted. That style can avoid unnecessary formatting work when a debug message is skipped.
For ordinary strings outside logging, do not mix formatting styles in the same expression. Combining %s, format(), and f-strings in one message makes reviews harder and increases the chance that a placeholder is missed. Pick one style per string.
Security matters too. Formatting should not be used to build SQL statements, shell commands, or HTML from untrusted input. Use query parameters, command argument lists, or an escaping library for those cases. String formatting is for presentation, not for creating trusted executable text.
The practical rule is: one %s can format one value, multiple placeholders need a tuple, mapping keys can avoid order mistakes, and %% is required for a literal percent sign.
Once those rules are clear, old-style formatting becomes much less surprising to debug.
Match A Single Placeholder
A template such as ‘Name: %s’ % name converts the supplied value to a string representation. The placeholder and argument should be kept together so future changes do not leave a missing or extra value.

Format Multiple Values
When a template has multiple markers, pass a tuple in the same order. Mapping-style placeholders can make named values clearer when a long template would otherwise depend on positional order.
Know The Conversion Codes
%s is general string conversion, while %d, %f, and related codes impose numeric formatting rules. An incompatible type should fail visibly rather than be silently presented as the wrong value.
Escape Literal Percent Signs
Use %% when the output must contain a literal percent sign. This matters in messages, percentages, URLs, and templates that mix formatting markers with ordinary punctuation.

Compare Modern Formatting
f-strings are often concise for expressions, and str.format supports reusable templates. Keep percent formatting when maintaining compatible legacy code, logging conventions, or an API that already defines it.
Test Arguments And Output
Test one and multiple values, tuples, mappings, numeric conversions, percent escaping, non-ASCII text, and missing or extra arguments. Assert the exact output when the string is part of an external interface.
The official printf-style formatting reference documents %s and related conversions. Related Python Pool references include strings and tests.
For related string workflows, compare string operations, exact-output tests, and format errors when choosing a formatter.
Frequently Asked Questions
What does %s do in Python?
In percent-style string formatting, %s converts a supplied value to a string representation and inserts it into the template.
How do I format multiple values with %s?
Supply a tuple with values in the same order as the placeholders, or use a mapping when named placeholders are appropriate.
How do I print a literal percent sign?
Escape a literal percent sign as %% inside a percent-format string.
Should I use %s or f-strings?
Percent formatting remains valid and useful in legacy code, but f-strings or str.format often make new code easier to read and extend.