Work with Strings in Python

PythonBeginner
Practice Now

Introduction

In this lab, you will gain hands-on experience working with strings in Python, a fundamental data type. You will begin by understanding string basics, including creation, immutability, and accessing individual characters using both positive and negative indexing.

Building upon this foundation, you will learn how to extract substrings using slicing, utilize various string operators and escape characters for manipulation and special formatting, and explore different methods for formatting strings. Finally, you will delve into common string methods to perform operations like searching, replacing, and modifying string content.

Understand String Basics and Indexing

In this step, you will learn the fundamental concepts of strings in Python, including how to create them and access individual characters using indexing. Strings are sequences of characters and are one of the most common data types. You can create strings using single quotes ('...') or double quotes ("...").

A key characteristic of Python strings is that they are immutable, meaning their contents cannot be changed after they are created. Any operation that appears to modify a string actually creates a new one.

Let's explore this. In the WebIDE, open the file string_basics.py from the ~/project directory in the file explorer on the left. Add the following code to it:

## string_basics.py

## Strings are immutable. Assigning a new string to a variable
## creates a new string object with a new memory address.
a = "hello"
print(f"Value: {a}, ID: {id(a)}")

a = "hi"
print(f"Value: {a}, ID: {id(a)}")

To run the script, open a terminal in the WebIDE (Terminal -> New Terminal) and execute the following command:

python ~/project/string_basics.py

You will see output similar to this, where the ID values are different, confirming that a new string object was created.

Value: hello, ID: <placeholder>
Value: hi, ID: <placeholder>

Now, let's explore string indexing. You can access individual characters using their index (position). In Python, indexing starts from 0 for the first character.

Modify the string_basics.py file to include positive indexing:

## string_basics.py
a = "Hello"

## Positive indexing (from the beginning)
print("Positive Indexing:")
print(a[0])
print(a[1])
print(a[2])
print(a[3])
print(a[4])

## Accessing an index that doesn't exist will cause an IndexError.
## print(a[5])

Save the file and run it again:

python ~/project/string_basics.py
Positive Indexing:
H
e
l
l
o

Python also supports negative indexing, which accesses characters from the end of the string. The last character is at index -1, the second to last is -2, and so on.

Add negative indexing examples to string_basics.py:

## string_basics.py
a = "Hello"

## Positive indexing (from the beginning)
print("Positive Indexing:")
print(a[0])
print(a[1])
print(a[2])
print(a[3])
print(a[4])

## Negative indexing (from the end)
print("\nNegative Indexing:")
print(a[-5])
print(a[-4])
print(a[-3])
print(a[-2])
print(a[-1])

## Because strings are immutable, you cannot change a character.
## The following line would cause a TypeError: 'str' object does not support item assignment
## a[0] = "J"

Save the file and run it one last time for this step:

python ~/project/string_basics.py
Positive Indexing:
H
e
l
l
o

Negative Indexing:
H
e
l
l
o

Slice Strings

In this step, you will learn how to extract substrings from a string using slicing. While indexing gets a single character, slicing gets a sequence of characters.

The basic syntax for slicing is string[start:end]. This extracts the part of the string from the start index up to, but not including, the end index.

Open the file string_slicing.py from the ~/project directory. Add the following code to demonstrate basic slicing:

## string_slicing.py
a = "Hello World"

## Slice from index 0 up to (but not including) index 5
print(a[0:5])

## Slice from index 6 to the end of the string
print(a[6:])

## Slice from the beginning up to (but not including) index 5
print(a[:5])

## Using negative indices for slicing
print(a[-5:-2])

## Get a copy of the entire string
print(a[:])

Save the file and run it from the terminal:

python ~/project/string_slicing.py
Hello
World
Hello
Wor
Hello World

Slicing can also take a third parameter, step, with the syntax string[start:end:step]. The step value determines the interval between characters in the slice.

Modify string_slicing.py to include examples with a step:

## string_slicing.py
a = "Hello World"

## ... (previous code) ...

b = "0123456789"

## Get every second character from the beginning to the end
print(b[::2])

## Get characters from index 1 to 7, with a step of 3
print(b[1:7:3])

## A negative step reverses the direction. This reverses the entire string.
print(b[::-1])

## Reverse from index 7 down to (but not including) index 2
print(b[7:2:-1])

Save the file and run it again:

python ~/project/string_slicing.py
Hello
World
Hello
Wor
Hello World
02468
14
9876543210
76543

Slicing is forgiving and automatically handles indices that are out of bounds, which prevents errors.

Add these final lines to string_slicing.py to see this behavior:

## string_slicing.py
a = "Hello World"

## ... (previous code) ...

b = "0123456789"

## ... (previous code) ...

## Slicing with out-of-bounds indices
c = "Python"
## The end index is larger than the string length, but it works fine.
print(c[2:100])

## The start index is before the beginning, but it works fine.
print(c[-100:4])

Save and run the script:

python ~/project/string_slicing.py
Hello
World
Hello
Wor
Hello World
02468
14
9876543210
76543
thon
Pyth

Use String Operators and Escape Characters

In this step, you will learn about common operators used with strings and how to use escape characters to represent special characters.

Python provides several operators for string manipulation. The in and not in operators check for substrings, + concatenates strings, and * repeats a string.

Open the file string_operators.py in the WebIDE and add the following code:

## string_operators.py

## 'in' operator checks if a substring exists within a string
print('e' in 'Hello')
print('x' in 'Hello')

## 'not in' operator is the opposite of 'in'
print('e' not in 'Hello')
print('x' not in 'Hello')

## Concatenation (+) joins two strings
print('Hello' + ' ' + 'World')

## Repetition (*) repeats a string a given number of times
print('=' * 20)
print('Go! ' * 3)

Save the file and run it:

python ~/project/string_operators.py
True
False
False
True
Hello World
====================
Go! Go! Go!

Next, let's look at escape characters. These are special sequences starting with a backslash (\) that represent non-printable or special characters.

Open the file escape_characters.py and add the following code:

## escape_characters.py

## Use \' or \" to include quotes inside a string
print('It\'s a beautiful day.')
print("He said, \"Python is fun!\"")

## \n creates a new line
print("First line\nSecond line")

## \t creates a horizontal tab
print("Column1\tColumn2\tColumn3")

## \\ represents a literal backslash
print("This is a backslash: \\")

## A raw string, prefixed with 'r', treats backslashes as literal characters.
## This is very useful for file paths and regular expressions.
print("A normal string: C:\\Users\\new_folder")
print(r"A raw string: C:\Users\new_folder")

Save the file and run it:

python ~/project/escape_characters.py
It's a beautiful day.
He said, "Python is fun!"
First line
Second line
Column1 Column2 Column3
This is a backslash: \
A normal string: C:\Users\new_folder
A raw string: C:\Users\new_folder

Format Strings

In this step, you will learn modern and effective ways to format strings in Python. This is crucial for creating dynamic and readable output by embedding variables and expressions within strings.

While you can use the + operator to concatenate strings, it becomes clumsy when mixing strings with non-string types like numbers, as you must manually convert them using str().

Python offers better solutions. The most common and recommended method is using f-strings (formatted string literals).

f-string Formatting

f-strings, introduced in Python 3.6, provide a concise and readable way to embed expressions inside strings. You simply prefix the string with f or F and write expressions inside curly braces {}.

Open the file string_formatting.py and add the following code:

## string_formatting.py

name = "Alice"
age = 30

## Using an f-string to embed variables
greeting = f"Hello, my name is {name} and I am {age} years old."
print(greeting)

## You can also embed expressions directly
print(f"In 5 years, I will be {age + 5} years old.")

Save and run the script:

python ~/project/string_formatting.py
Hello, my name is Alice and I am 30 years old.
In 5 years, I will be 35 years old.

Format Specifiers

f-strings also allow you to control the formatting of the embedded values using format specifiers, which follow a colon (:) inside the braces.

Add the following examples to string_formatting.py:

## string_formatting.py

## ... (previous code) ...

pi = 3.14159265

## Format a float to 2 decimal places
print(f"The value of pi is approximately {pi:.2f}")

## Pad a number with leading zeros to a width of 8
order_id = 45
print(f"Order ID: {order_id:08}")

## Align text within a given space (width of 10)
## < (left), ^ (center), > (right)
text = "Python"
print(f"'{text:<10}'")
print(f"'{text:^10}'")
print(f"'{text:>10}'")

## Add comma as a thousand separator
large_number = 1234567890
print(f"A large number: {large_number:,}")

Save and run the script again:

python ~/project/string_formatting.py
Hello, my name is Alice and I am 30 years old.
In 5 years, I will be 35 years old.
The value of pi is approximately 3.14
Order ID: 00000045
'Python    '
'  Python  '
'    Python'
A large number: 1,234,567,890

The str.format() Method

Before f-strings, the str.format() method was the preferred way to format strings. It works by placing placeholder braces {} in the string and then passing values into the format() method.

Add this example to the end of string_formatting.py:

## string_formatting.py

## ... (previous code) ...

## Using the str.format() method
item = "moon"
cost = 99.95
statement = "The {} costs {:.2f} dollars.".format(item, cost)
print(statement)

Save and run the file to see the output:

python ~/project/string_formatting.py
Hello, my name is Alice and I am 30 years old.
In 5 years, I will be 35 years old.
The value of pi is approximately 3.14
Order ID: 00000045
'Python    '
'  Python  '
'    Python'
A large number: 1,234,567,890
The moon costs 99.95 dollars.

While str.format() is still useful, f-strings are generally more readable and faster.

Explore Common String Methods

In this final step, you will explore some of the most common and useful built-in methods for string objects. These methods perform various operations like changing case, finding and replacing text, and splitting strings into lists.

Remember that strings are immutable, so these methods always return a new string and do not modify the original one.

Open the file string_methods.py and add the following code to see these methods in action:

## string_methods.py

## Case conversion methods
s1 = "Hello, World!"
print(f"Original: '{s1}'")
print(f"Upper case: '{s1.upper()}'")
print(f"Lower case: '{s1.lower()}'")
print(f"Title case: '{s1.title()}'")
print("-" * 20)

## Searching and replacing
s2 = "The quick brown fox jumps over the lazy dog."
print(f"Original: '{s2}'")
## Check if a string starts or ends with a substring
print(f"Starts with 'The': {s2.startswith('The')}")
print(f"Ends with 'dog.': {s2.endswith('dog.')}")
## Find the index of a substring (-1 if not found)
print(f"Index of 'fox': {s2.find('fox')}")
## Replace a substring with another
s3 = s2.replace("brown", "red")
print(f"After replace: '{s3}'")
print("-" * 20)

## Stripping whitespace
s4 = "    some whitespace    "
print(f"Original: '{s4}'")
## strip() removes from both ends, lstrip() from left, rstrip() from right
print(f"Stripped: '{s4.strip()}'")
print("-" * 20)

## Splitting and joining
s5 = "one,two,three,four"
print(f"Original: '{s5}'")
## Split the string into a list of substrings based on a delimiter
parts = s5.split(',')
print(f"Split list: {parts}")
## Join the elements of a list into a single string with a separator
s6 = " ".join(parts)
print(f"Joined string: '{s6}'")

Save the file and run it from the terminal:

python ~/project/string_methods.py

Your output should look like this:

Original: 'Hello, World!'
Upper case: 'HELLO, WORLD!'
Lower case: 'hello, world!'
Title case: 'Hello, World!'
--------------------
Original: 'The quick brown fox jumps over the lazy dog.'
Starts with 'The': True
Ends with 'dog.': True
Index of 'fox': 16
After replace: 'The quick red fox jumps over the lazy dog.'
--------------------
Original: '    some whitespace    '
Stripped: 'some whitespace'
--------------------
Original: 'one,two,three,four'
Split list: ['one', 'two', 'three', 'four']
Joined string: 'one two three four'

These are just a few of the many string methods available in Python. They provide powerful tools for processing and manipulating text data.

Summary

In this lab, you have learned the fundamental concepts of working with strings in Python. You started with the basics, understanding how to create strings and recognizing their immutable nature. You practiced accessing individual characters with both positive and negative indexing and extracting substrings using slicing with start, end, and step parameters.

You then explored string operators for concatenation (+) and repetition (*), and learned how to use escape characters to include special characters in your strings. You mastered modern string formatting techniques, focusing on the power and readability of f-strings and their format specifiers, while also seeing the str.format() method. Finally, you practiced using common string methods like upper(), lower(), replace(), strip(), split(), and join() to perform essential text manipulation tasks.