Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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?

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.Support on Ko-Fi

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 example f"{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 plain str values, so do not use them in code that must run on older interpreters or expect str output.
  • Bytes literals create bytes, not str. A b prefix 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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.