Skip to content

Strings in Python

A string is a sequence of characters enclosed in quotation marks. In Python, strings are ordered sequences of character data, and thus can be indexed in this way. You can access individual characters of a string using indexing and a range of characters using slicing. Strings are immutable data types, which means that once a string is created, you can’t modify it.

In this tutorial, we’ll learn everything about Python strings, from how to create and format strings to the different methods you can use to manipulate and work with string data.

In Python, you can create strings by enclosing a sequence of characters within a pair of single or double quotes. For example:

strings.py
# Single word
print('hello')
 
# Entire phrase
print('This is also a string')
 
# We can also use double quote
print("String built with double quotes")

Output:

command
C:\Users\Your Name> python strings.py
hello
This is also a string
String built with double quotes

In Python, string is an object of type str class. You can verify this with the type() function:

strings.py
a = "Hello"
print(type(a))

Output:

command
C:\Users\Your Name> python strings.py
<class 'str'>

Assigning a string to a variable is as simple as assigning a value to a variable. For example:

strings.py
# You can use single or double quotes
a = "Hello" 
b = 'Hello'
print(a)
print(b)

Output:

command
C:\Users\Your Name> python strings.py
Hello
Hello

In Python, you can assign a multiline string to a variable by using three quotes:

strings.py
a = """Lorem ipsum dolor sit amet,
consectetur adipiscing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua."""
 
# You can also use three single quotes:
b = '''Lorem ipsum dolor sit amet,
consectetur adipiscing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.'''
 
print(a)
print("------")
print(b)

Output:

command
C:\Users\Your Name> python strings.py
Lorem ipsum dolor sit amet,
consectetur adipiscing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
------
Lorem ipsum dolor sit amet,
consectetur adipiscing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.

In Python, strings are arrays of bytes representing Unicode characters. A string can be thought of as an array of characters. Like other programming languages, Python strings are indexed starting from 0. For example:

strings.py
a = "Hello, World!"
print(a[1])

Output:

command
C:\Users\Your Name> python strings.py
e

To get the length of a string, use the len() function:

strings.py
a = "Hello, World!"
print(len(a))

Output:

command
C:\Users\Your Name> python strings.py
13

Strings are iterable objects, which means you can iterate through each character of the string using a for loop. For example:

strings.py
for x in "cricket":
  print(x)

Output:

command
C:\Users\Your Name> python strings.py
c
r
i
c
k
e
t

To check if a certain phrase or character is present in a string, we can use the keyword in.

strings.py
txt = "Nothing is impossible, you need to believe"
print("impossible" in txt)

Output:

command
C:\Users\Your Name> python strings.py
True

To check if a certain phrase or character is not present in a string, we can use the keyword not in.

strings.py
txt = "Nothing is impossible, you need to believe"
print("possible" not in txt)

Output:

command
C:\Users\Your Name> python strings.py
True

Immutable means every method returns a new string

Section titled “Immutable means every method returns a new string”

Nothing you call on a string changes it. The original is still there, untouched:

diagram Diagram mermaid
immutable.py
s = "hello"
s.upper()        # 'HELLO'
print(s)         # 'hello'   <- unchanged; the result was discarded
s = s.upper()    # you must reassign
 
s[0] = "H"       # TypeError: 'str' object does not support item assignment

Forgetting to reassign is the single most common string bug — s.strip() on its own line does nothing at all.

Which is why += in a loop is the wrong tool

Section titled “Which is why += in a loop is the wrong tool”

Each += builds a whole new string and copies everything so far. Measured, 20,000 characters:

approachtimevs +=
s += "x" in a loop13.73 ms1.0×
"".join(generator)5.91 ms2.3× faster
"".join(list)1.44 ms9.6× faster
building.py
s = ""
for i in range(n):
    s += "x"                  # 13.73 ms — quadratic in disguise
 
s = "".join("x" for i in range(n))   #  5.91 ms
s = "".join(["x"] * n)               #  1.44 ms

join walks the pieces once to total their length, allocates the result a single time, then copies each piece into place. The list form beats the generator form because join can measure a list up front but must materialise a generator first.

len counts code points, not bytes and not what you would call characters. Click through the samples and watch the three numbers come apart.

sketch Length, bytes, and what the eye sees p5.js
len counts code points. An emoji is one code point but four UTF-8 bytes, and an accented letter may be one code point or two depending on normal form.

Measured:

stringlenUTF-8 bytes
"cafe"44
"café" written with U+00E945
"café" written as e + combining accent56
one emoji14

The two spellings of café print identically and compare unequal, because one is five code points and the other four. Normalise before comparing text that came from outside your program:

normalize.py
import unicodedata
a = "caf\u00e9"        # NFC: e-acute as one code point
b = "cafe\u0301"       # NFD: e + combining acute
a == b                                          # False
unicodedata.normalize("NFC", b) == a            # True

strip takes a set of characters, not a suffix

Section titled “strip takes a set of characters, not a suffix”

This is the string bug most likely to reach production, because the obvious test case passes:

strip_trap.py
"banana.txt".strip(".txt")      # 'banana'   <- looks right!
"text.txt".strip(".txt")        # 'e'        <- everything in ".txt" stripped from BOTH ends
"xxt.txt".strip(".txt")         # ''         <- the whole string is gone
 
"text.txt".removesuffix(".txt")  # 'text'    <- what you actually meant

strip(".txt") removes any of the characters ., t, x repeatedly from both ends. "banana.txt" survives only because b is not in that set. Use removesuffix (3.9+) or slice by length.

slicing.py
s = "python"
s[2:4]     # 'th'
s[::-1]    # 'nohtyp'
s[99:]     # ''      <- no error
s[99]      # IndexError: string index out of range

And in tests for a substring, not a word: "cat" in "concatenate" is True. Use .find() when you want a position and can tolerate absence — it returns -1 rather than raising, unlike .index().

pch.quizTag pch.quizDefaultTitle
  1. What does 'text.txt'.strip('.txt') return?

    pch.quizShowAnswer

    C — 'e' — strip takes a SET of characters and removes any of '.', 't', 'x' from both ends repeatedly, leaving 'e'. Use removesuffix('.txt') to strip a suffix. 'banana.txt' happens to give the right answer, which is why the bug survives testing.

  2. Building a 20,000-character string took 13.73 ms with += in a loop and 1.44 ms with ''.join(list). Why is join faster?

    pch.quizShowAnswer

    B — strings are immutable, so each += allocates a new string and copies everything so far — Each += builds a whole new string. join totals the lengths once, allocates the result a single time, and copies each piece in.

  3. Two strings both display as 'café' but compare unequal. What is the most likely reason?

    pch.quizShowAnswer

    B — one uses a single code point for the accented e, the other uses e plus a combining accent — NFC spells it as 4 code points and NFD as 5. They render identically and are different strings. Normalise with unicodedata.normalize('NFC', s) before comparing.

  4. What is the result of s.upper() on its own line, where s = 'hello'?

    pch.quizShowAnswer

    B — nothing observable: a new string is created and discarded, s is still 'hello' — Every string method returns a new string and leaves the original alone. You must write s = s.upper(). The same trap applies to strip, replace and lower.

In this tutorial, we learned how to create strings, assign strings to variables, and access string characters using indexing and slicing. We also learned how to get the length of a string, iterate through a string using a loop, and check if a string contains a certain phrase or character. For more information on strings, check out the official Python documentation. For more tutorials, Visit Python Central Hub.

Section titled “In this tutorial, we learned how to create strings, assign strings to variables, and access string characters using indexing and slicing. We also learned how to get the length of a string, iterate through a string using a loop, and check if a string contains a certain phrase or character. For more information on strings, check out the official Python documentation. For more tutorials, Visit Python Central Hub.”

pch.coffeeTagline

pch.coffeeCta

pch.feedbackHeading

pch.feedbackSubheading