Recommended Free Tools
iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
You create a string in Python by writing a literal in quotes for fixed text, an f-string when values must be embedded, str() when converting an object, + for a simple runtime combination, and ''.join(parts) or io.StringIO when assembling many fragments. The right choice depends on whether the text is fixed or computed, whether it spans lines or contains backslashes, how many pieces you are joining, and which Python version your code must support.
Start with the type: str is text
Python’s text type is str, an immutable Unicode sequence, as described in the Python 3.12 Built-in Types reference. Immutability matters for every method below: you never edit a string in place. Each operation produces a new string, which is why assembly strategy matters once you build text from many pieces. The one exception to “every method creates str” is the bytes literal, covered at the end.
Quoted literals for fixed text
Literals are the simplest way to create a string. The Python 3.14 lexical analysis reference defines single quotes, double quotes and triple quotes as string literal delimiters.
Single and double quotes
single = 'Hello'
double = "Hello"
Both forms create the same type of object. Pick one quote style and stick with it in a given codebase. When the text itself contains one quote character, use the other style so you avoid escaping: "It's ready" works without a backslash.
#1 Best Overall
Triple quotes for multiline text
message = """First line
Second line"""
Triple-quoted literals can contain real newlines, and the newlines and indentation inside them are kept in the value. If you want the text to start on the line after the opening delimiter but not include the first newline, place a backslash immediately after the opening triple quotes. Indented triple-quoted blocks inside functions will carry that indentation into the string, so indent carefully or build the text another way.
Raw strings for backslash-heavy text
pattern = r"d{4}-d{2}-d{2}"
The r prefix leaves backslashes as written instead of processing escape sequences such as n. This is most useful for regular expressions and file paths. A raw string still follows quoting rules, and it cannot end in an odd number of backslashes, because the final backslash would escape the closing quote.
Combining fixed pieces: adjacent literals, + and *
Adjacent literals
message = (
"Put several strings within parentheses "
"to make a long literal easier to read."
)
Adjacent string literals are joined at parse time, as part of the syntax described in the Python 3.14 expressions reference. This is a source-code convenience for long fixed text. It does not work with variables: "Hello " name is a syntax error, and you need +, an f-string or another method for runtime values.
Rank #2
The + and * operators
language = "Py" + "thon"
repeated = "ha" * 3
+ concatenates two strings at runtime, and * repeats a string. Both are clear for a handful of operands. Building a result by repeatedly applying + inside a large loop is the wrong pattern; use the fragment-collection methods described below.
Inserting values into text
f-strings
name = "Ada"
count = 3
message = f"{name} wrote {count} examples"
An f-string evaluates each expression inside braces and inserts the result. The official Python 3.13 input and output tutorial shows expression fields and numeric precision, such as a format specifier that limits a float to three decimal places:
import math
message = f"pi is about {math.pi:.3f}"
# pi is about 3.142
F-strings are usually the clearest choice when a fixed sentence contains a few runtime values. They are a formatting feature, so they require the version notes covered later in this article.
str.format() and format()
message = "{} wrote {} examples".format("Ada", 3)
price = format(12.5, ".2f")
# price is '12.50'
str.format() keeps the template separate from the values, which helps when the template is stored in a constant or loaded from configuration. The built-in format() function formats a single value with a format specification. The specification mini-language is shared across these mechanisms, though details vary by the type being formatted.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Converting a value with str()
count = 3
label = "count=" + str(count)
str(object) returns that object’s string representation. Use it when you need a plain string from a number or other object before concatenating. Bytes are different: to turn encoded bytes into text, decode them with an encoding, for example str(data, "utf-8"), and optionally an error policy. Decoding is an interpretation decision about the bytes, not simple formatting.
Assembling many fragments
When you build text in a loop or from many pieces, collect the parts and assemble once. The built-in types reference names str.join() and io.StringIO as the efficient methods for building a string from multiple fragments.
str.join()
parts = ["red", "green", "blue"]
colors = ", ".join(parts)
# colors is 'red, green, blue'
Use join() when you already have a list or other iterable of strings. The separator is the string on which you call the method, so "n".join(lines) creates a newline-separated block. Every item must be a str; convert numbers first.
io.StringIO
from io import StringIO
buffer = StringIO()
for part in parts:
buffer.write(part)
result = buffer.getvalue()
StringIO suits incremental, file-like writing, such as when a function receives a writable object and you want to produce text without touching a real file. Call getvalue() once at the end. The documentation does not give a universal size threshold where one method beats the other, so treat join() for lists you already hold and StringIO for write-as-you-go code as sound patterns rather than measured speed rules.
Choosing a method
Compare the options on four questions: is the content fixed or computed, does it span lines or contain backslashes, is this a one-off combination or many fragments, and does the target Python version support it?
Best Value
| Method | Best for | Fixed or runtime values | Multiline or backslashes | Many fragments | Minimum Python |
|---|---|---|---|---|---|
| Quoted literal | Fixed text | Fixed only | Single-line; escapes processed | Not applicable | Any Python 3 release |
| Triple-quoted literal | Fixed multiline blocks | Fixed only | Multiline; newlines kept | Not applicable | Any Python 3 release |
Raw literal (r"...") |
Regex patterns, Windows paths | Fixed only | Backslashes kept as written | Not applicable | Any Python 3 release |
| Adjacent literals | Long fixed text split across lines | Fixed only, no variables | Works with any literal form | Not applicable | Any Python 3 release |
+ operator |
Joining two or three values | Runtime, both sides must be str |
Not affected | Poor for large loops | Any Python 3 release |
| f-string | Sentences with embedded values | Runtime, expressions allowed | Works in triple-quoted form | Not applicable | Python 3.6 |
str.format() / format() |
Templates stored apart from values | Runtime | Not affected | Not applicable | Any Python 3 release |
str() |
Converting one object to text | Runtime | Not applicable | Not applicable | Any Python 3 release |
str.join() |
Combining an existing list of strings | Runtime | Separator can be "n" |
Preferred | Any Python 3 release |
io.StringIO |
Incremental writing | Runtime | Not affected | Preferred | Any Python 3 release |
The “Any Python 3 release” entries describe features the cited reference pages present as core behavior; they are not version-gated in those references. The only version-gated rows are f-strings and the newer syntax covered below.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Version and type notes
- F-strings require Python 3.6 or later. The Python 3.14 lexical analysis reference records their introduction in 3.6, the
=debug specifier in 3.8, and the removal of many expression restrictions in 3.12. In 3.12 and later, you can reuse the same quote type inside an f-string’s braces, for examplef"{d["key"]}". Earlier versions reject that code, so use different quote types there. - Template string literals (
t"...") require Python 3.14. The same reference lists them as added in 3.14. They produce template objects rather than plainstrvalues, so do not use them in code that must run on older interpreters or expectstroutput. - Bytes literals create
bytes, notstr. Abprefix makes a bytes literal, and bytes and str literals cannot be combined through adjacency. Decode bytes when you need text, and encode text when you need bytes for output.
Practical rule of thumb
Use a plain literal when nothing varies, a triple-quoted literal for fixed blocks, an f-string for sentences with values, str() for explicit conversion, and join() or StringIO once fragments start to accumulate. Code that combines many fragments with + is harder to read and to scale than code that gathers the pieces first.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

