LearnFrenzy
Sign in Take a free test

Strings · Lesson 14 of 39

Strings, Indexing and Slicing

4 min read Updated Nov 7, 2026 Saurabh Samir

Text is everywhere: names, messages, URLs, CSV rows, chatbot replies. In Python, text is a str – an ordered sequence of characters. Once you can pick characters out of a string and cut it into pieces, a huge range of everyday problems becomes easy.

In this lesson

  • Positive and negative indexes
  • Slicing with [start:stop:step]
  • Why strings can't be changed in place
  • Escape characters, raw strings and multi-line text

Every character has a position

Positions (indexes) start at 0. Python also counts from the end with negative indexes: -1 is the last character.

word = "PYTHON"

  1. P0-6
  2. Y1-5
  3. T2-4
  4. H3-3
  5. O4-2
  6. N5-1

Top row: index from the start. Bottom row: index from the end.

word = "PYTHON"
print(word[0])
print(word[3])
print(word[-1])
print(word[-2])
print(len(word))

Output

P
H
N
O
6

The last valid index is always len(word) - 1. Asking for word[6] raises IndexError: string index out of range.

Slicing: taking a piece

A slice text[start:stop] returns the characters from start up to, but not including, stop – the same rule as range(). Either side can be left out.

word = "PYTHON"
print(word[0:2])    # from 0 up to 2
print(word[2:])     # from 2 to the end
print(word[:4])     # from the start up to 4
print(word[-3:])    # last three
print(word[:])      # a full copy

Output

PY
THON
PYTH
HON
PYTHON

A helpful way to picture slices

Think of the indexes as sitting between the characters, like cuts on a ruler: |P|Y|T|H|O|N| with cuts numbered 0 to 6. word[1:4] takes everything between cut 1 and cut 4: YTH.

Slices never raise IndexError – out-of-range values are simply clipped:

print("hi"[0:100])
print("hi"[5:])     # empty string

Output

hi

The step

A third number sets the step. A negative step walks backwards – which gives the famous one-line reverse:

digits = "0123456789"
print(digits[::2])     # every second character
print(digits[1::3])    # start at 1, every third
print(digits[::-1])    # reversed

word = "level"
print(word == word[::-1])   # palindrome check

Output

02468
147
9876543210
True

Strings are immutable

You cannot change a character inside a string. Any "change" builds a new string:

name = "kavya"
# name[0] = "K"   → TypeError: 'str' object does not support item assignment
name = "K" + name[1:]
print(name)
print(name.upper(), name)   # methods return new strings, too

Output

Kavya
KAVYA Kavya

Common mistake: calling a method and ignoring the result

name.upper() on its own line does nothing useful – the original is unchanged. Store the result: name = name.upper().

Joining, repeating and checking

first, last = "Ravi", "Kumar"
print(first + " " + last)
print("-" * 20)
print("Kum" in last)
print(len(first + last))

for ch in "abc":
    print(ch.upper(), end="")

Output

Ravi Kumar
--------------------
True
9
ABC

Escape characters

A backslash gives the next character a special meaning:

EscapeMeaning
\nnew line
\ttab
\' \"a quote inside the same kind of quotes
\\a real backslash
print("Name:\tAsha\nCity:\tPune")
print('It\'s fine')
print("C:\\Users\\asha")

Output

Name:	Asha
City:	Pune
It's fine
C:\Users\asha

Raw strings

Put r before the quotes and backslashes are kept as they are. Use raw strings for Windows paths and regular expressions:

print(r"C:\new\test")
print("C:\new\test")    # \n and \t are interpreted!

Output

C:\new\test
C:
ew	est

Multi-line strings

message = """Dear Customer,
Your order has shipped.
Thank you!"""
print(message)
print(message.count("\n") + 1, "lines")

Output

Dear Customer,
Your order has shipped.
Thank you!
3 lines

Characters and numbers

Every character has a Unicode number. ord() gives the number and chr() goes back – useful for simple ciphers:

print(ord("A"), ord("a"), chr(66))

secret = ""
for ch in "HAL":
    secret += chr(ord(ch) + 1)   # shift each letter by one
print(secret)

Output

65 97 B
IBM

Practice

Try it yourself

  1. From email = "meera.iyer@learnfrenzy.com", print the part before @ and the domain after it using slicing and .index("@").

    Show solution
    email = "meera.iyer@learnfrenzy.com"
    at = email.index("@")
    print(email[:at])
    print(email[at + 1:])

    Output

    meera.iyer
    learnfrenzy.com
  2. Mask a card number so only the last four digits show: "4111222233334444" → "************4444".

    Show solution
    card = "4111222233334444"
    print("*" * (len(card) - 4) + card[-4:])

    Output

    ************4444

Quick check

What is "PYTHON"[1:4]?

"YTH"

What is "PYTHON"[-1]?

"N", the last character.

Why does s[0] = "X" fail?

Strings are immutable. Build a new one instead: s = "X" + s[1:].

Summary

  • Indexes start at 0; negative indexes count from the end.
  • s[start:stop:step] slices; stop is excluded; s[::-1] reverses.
  • Strings are immutable – operations return new strings.
  • Use escapes like \n and \t, or raw strings r"..." to keep backslashes.

Finished this lesson?

Mark it complete to track your progress, then carry on with the next lesson.

Next lesson

Search LearnFrenzy

Esc

Quick links