Strings in Python
Mastering Python Strings
Section titled “Mastering Python Strings”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.
Creating Strings
Section titled “Creating Strings”In Python, you can create strings by enclosing a sequence of characters within a pair of single or double quotes. For example:
# 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:
C:\Users\Your Name> python strings.py
hello
This is also a string
String built with double quotesString Type
Section titled “String Type”In Python, string is an object of type str class. You can verify this with the type() function:
a = "Hello"
print(type(a))Output:
C:\Users\Your Name> python strings.py
<class 'str'>Assign String to a Variable
Section titled “Assign String to a Variable”Assigning a string to a variable is as simple as assigning a value to a variable. For example:
# You can use single or double quotes
a = "Hello"
b = 'Hello'
print(a)
print(b)Output:
C:\Users\Your Name> python strings.py
Hello
HelloMultiline Strings
Section titled “Multiline Strings”In Python, you can assign a multiline string to a variable by using three quotes:
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:
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.Strings Arrays
Section titled “Strings Arrays”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:
a = "Hello, World!"
print(a[1])Output:
C:\Users\Your Name> python strings.py
eLength of a String
Section titled “Length of a String”To get the length of a string, use the len() function:
a = "Hello, World!"
print(len(a))Output:
C:\Users\Your Name> python strings.py
13Going through a String with a Loop
Section titled “Going through a String with a Loop”Strings are iterable objects, which means you can iterate through each character of the string using a for loop. For example:
for x in "cricket":
print(x)Output:
C:\Users\Your Name> python strings.py
c
r
i
c
k
e
tFinding a String in a String
Section titled “Finding a String in a String”To check if a certain phrase or character is present in a string, we can use the keyword in.
txt = "Nothing is impossible, you need to believe"
print("impossible" in txt)Output:
C:\Users\Your Name> python strings.py
TrueNot Finding a String in a String
Section titled “Not Finding a String in a String”To check if a certain phrase or character is not present in a string, we can use the keyword not in.
txt = "Nothing is impossible, you need to believe"
print("possible" not in txt)Output:
C:\Users\Your Name> python strings.py
TrueImmutable 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:
flowchart LR S["s = 'hello'"] --> M["s.upper()"] M --> N["new object 'HELLO'"] S --> U["s is still 'hello'"] S --> A["s[0] = 'H'"] A --> E["TypeError:
'str' object does not
support item assignment"]
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 assignmentForgetting 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:
| approach | time | vs += |
|---|---|---|
s += "x" in a loop | 13.73 ms | 1.0× |
"".join(generator) | 5.91 ms | 2.3× faster |
"".join(list) | 1.44 ms | 9.6× faster |
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 msjoin 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.
See it move
Section titled “See it move”len counts code points, not bytes and not what you would call characters. Click
through the samples and watch the three numbers come apart.
Measured:
| string | len | UTF-8 bytes |
|---|---|---|
"cafe" | 4 | 4 |
"café" written with U+00E9 | 4 | 5 |
"café" written as e + combining accent | 5 | 6 |
| one emoji | 1 | 4 |
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:
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 # Truestrip 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:
"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 meantstrip(".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.
Indexing raises, slicing does not
Section titled “Indexing raises, slicing does not”s = "python"
s[2:4] # 'th'
s[::-1] # 'nohtyp'
s[99:] # '' <- no error
s[99] # IndexError: string index out of rangeAnd 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().
Check yourself
Section titled “Check yourself”-
What does 'text.txt'.strip('.txt') return?
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.
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.
-
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?
Each += builds a whole new string. join totals the lengths once, allocates the result a single time, and copies each piece in.
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.
-
Two strings both display as 'café' but compare unequal. What is the most likely reason?
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.
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.
-
What is the result of s.upper() on its own line, where s = '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.
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.
Conclusion
Section titled “Conclusion”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.”Try it: String Exercises
Section titled “Try it: String Exercises”Exercise 1 – Create and Print a String
Section titled “Exercise 1 – Create and Print a String”Exercise 2 – String Length
Section titled “Exercise 2 – String Length”Exercise 3 – String Indexing
Section titled “Exercise 3 – String Indexing”pch.coffeeTagline
pch.coffeeCtapch.feedbackHeading
pch.feedbackSubheading