DevHireLab
Tutorials
BootcampProblemsCode SimulatorAI InterviewSoonContact
DevHireLab
Tutorials
BootcampProblemsCode SimulatorAI InterviewSoonContact
Getting Started
01
What is Python and Why Learn It in 2026
02
Installing Python on Windows, Mac, and Linux
03
Setting up VS Code / PyCharm for Python
04
Understanding the Python Interpreter and REPL
05
Writing and Running Your First Python Program
06
Python Syntax and Indentation Rules
Variables and Data Types
01
Variables and Naming Conventions in Python
02
Numbers in Python (int, float, complex)
03
Strings and String Methods in Python
04
Booleans in Python
05
Type Conversion / Casting in Python
06
Understanding the None Type in Python
Operators
01
Arithmetic Operators in Python
02
Comparison Operators in Python
03
Logical Operators in Python
04
Assignment Operators in Python
05
Bitwise Operators in Python
06
Identity (is) and Membership (in) Operators
07
Walrus Operator (:=) in Python
Input, Output & Strings
01
input() and print() Functions in Python
02
f-strings and String Formatting in Python
03
String Slicing and Indexing in Python
04
Common String Methods (split, join, strip, replace)
05
Escape Characters in Python Strings
Control Flow
01
if, elif, else Statements in Python
02
Nested Conditionals in Python
03
for Loops in Python
04
while Loops in Python
05
break, continue, and pass Statements
06
Loop with else Clause in Python
07
match-case (Structural Pattern Matching)
Data Structures
01
Python Lists: Creation, Indexing, Slicing, Methods
02
Python Tuples and Immutability
03
Python Sets and Set Operations
04
Python Dictionaries: Keys, Values, and Methods
05
List Comprehensions in Python
06
Dictionary & Set Comprehensions in Python
07
Working with Nested Lists and Dictionaries
Functions
01
Defining and Calling Functions in Python
02
Function Arguments: Positional, Keyword, Default
03
*args and **kwargs in Python
04
Return Statements in Python Functions
05
Lambda Functions in Python
06
Recursion in Python
07
Variable Scope: Local, Global, Nonlocal
08
Docstrings and Function Annotations
Functional Programming Basics
01
map(), filter(), and reduce() in Python
02
Closures in Python Explained
03
Python Decorators: Basic to Advanced
04
Generators and yield in Python
Object-Oriented Programming (OOP)
01
Classes and Objects in Python
02
The init Constructor in Python
03
Instance vs Class Variables in Python
04
Inheritance in Python (Single, Multiple, Multilevel)
05
Polymorphism in Python
06
Encapsulation in Python
07
Abstraction in Python with the abc Module
08
Magic/Dunder Methods in Python
09
Static and Class Methods in Python
10
The @property Decorator in Python
11
Python Dataclasses Explained
Error Handling
01
try, except, finally in Python
02
Handling Multiple Exceptions in Python
03
Raising Custom Exceptions in Python
04
Understanding Python's Exception Hierarchy
05
Assertions in Python
File Handling
01
Reading and Writing Text Files in Python
02
Working with the with Statement in Python
03
Working with CSV Files in Python
04
Working with JSON Files in Python
05
Working with Directories (os, pathlib) in Python
Modules and Packages
01
Importing Built-in Modules in Python
02
Creating Your Own Modules in Python
03
Understanding Packages and init.py
04
Python Standard Library Overview
05
Installing Packages with pip
Advanced Core Concepts
01
Iterators and Iterables in Python
02
Context Managers in Python (with, contextlib)
03
Multithreading Basics in Python
04
Multiprocessing Basics in Python
05
Asyncio Basics: async/await in Python
06
Memory Management and Garbage Collection in Python
07
Type Hints in Python (typing module)

String Slicing and Indexing in Python

Every character in a Python string sits at a specific position, and python string indexing and python string slicing are how you reach in and grab exactly what you need — a single character, or an entire chunk. You've seen the basics of this already in the earlier strings article; this one goes deeper into the mechanics, the step parameter, and the errors each approach can (and can't) raise.

Introduction: Strings as Sequences of Characters

A string in Python behaves like an ordered sequence of characters, and every character has a numbered position. Indexing lets you grab a single character at a specific position. Slicing lets you extract an entire range — a substring.

Python counts positions two ways at once: positive indices start at 0 and count from the left, while negative indices start at -1 and count from the right.

 P   y   t   h   o   n
 0   1   2   3   4   5
-6  -5  -4  -3  -2  -1

Both indexing systems point at the same characters — they're just two different directions to count from, and Python lets you use whichever is more convenient for a given situation.

Indexing: Accessing Single Characters

Basic syntax
word = "Python"

print(word[0])    # P  — first character (positive indexing)
print(word[-1])   # n  — last character (negative indexing)
print(word[2])    # t  — third character
print(word[-2])   # o  — second-to-last character
Walking through an example
word = "Python"

print(word[0])   # P
print(word[1])   # y
print(word[5])   # n
print(word[-6])  # P — same character as word[0], counted from the other direction
Common error: IndexError

Try to access a position that doesn't exist, and indexing raises an error rather than silently returning something like an empty result:

word = "Python"
print(word[10])
# IndexError: string index out of range

This is worth internalizing early, because it behaves very differently from slicing, which handles out-of-range positions gracefully — covered next.

Slicing: Extracting Substrings

Basic syntax

Slicing uses the syntax s[start:end], where start is inclusive and end is exclusive — the character at the end position itself is not included in the result.

word = "Python"

print(word[0:3])   # Pyt — characters at index 0, 1, 2 (not 3)
print(word[2:5])   # tho — characters at index 2, 3, 4 (not 5)
Omitting start or end

Leaving either side blank tells Python to default to the beginning or end of the string:

word = "Python"

print(word[:3])    # Pyt — from the start up to (not including) index 3
print(word[3:])    # hon — from index 3 to the end
print(word[:])     # Python — the entire string, unchanged
Negative indices in slices

You can mix negative indices into slicing the same way you can with plain indexing:

word = "Python"

print(word[-3:])    # hon — the last 3 characters
print(word[:-3])    # Pyt — everything except the last 3 characters
print(word[-4:-1])  # tho — from the 4th-from-last up to (not including) the last
Slicing never raises an error

This is the key difference from indexing, and it's worth remembering: slicing handles out-of-bounds positions gracefully, simply returning as much as it can, rather than raising a python IndexError.

word = "Python"

print(word[2:100])   # thon — Python just stops at the actual end of the string
print(word[100:200]) # '' — an empty string, no error at all

If you try the equivalent with plain indexing — word[100] — you'd get an IndexError immediately. Slicing is deliberately more forgiving, which makes it safer to use when you're not certain a given range actually exists within the string.

The Step Parameter: s[start:end:step]

Slicing supports a third component: step, which controls how many characters to skip between each one included in the result.

Skipping characters
word = "Python"

print(word[::2])    # Pto — every second character, starting from index 0
print(word[1::2])   # yhn — every second character, starting from index 1
print(word[::3])    # Ph  — every third character
Negative step: reversing direction

A negative step tells Python to walk backward through the string instead of forward:

word = "Python"

print(word[::-1])    # nohtyP — the entire string, reversed
print(word[5:0:-1])  # nohty — from index 5 down to (not including) index 0

That first example — s[::-1] — is the standard idiom for reverse string python: no start or end specified (so it defaults to covering the whole string), and a step of -1 walking backward one character at a time.

Practical example: extracting a pattern

The step parameter is genuinely useful any time you need to pull out data at a regular interval — extracting every third character from a fixed-format code, or reading a simple pattern embedded at regular positions within a string:

encoded = "HXeXlXlXoX"
message = encoded[::2]
print(message)   # Hello — every other character reconstructs the hidden message

Practical Applications and Immutability

Parsing fixed-width data

Slicing is a natural fit whenever you're working with data that has a predictable, fixed structure — a date string in a known format, or a log line where certain fields always sit at the same position:

date_string = "20260709"   # YYYYMMDD

year = date_string[:4]
m date_string[4:6]
day = date_string[6:]

print(f"{year}-{month}-{day}")   # 2026-07-09
Inserting or replacing substrings via slicing and concatenation

Because strings are immutable, you can't directly insert or replace a portion of a string in place — but slicing combined with concatenation gets you there by building a new string:

word = "Python"

# "Insert" a substring by slicing around the target position
modified = word[:2] + "XYZ" + word[2:]
print(modified)   # PyXYZthon
Reminder: strings are immutable

As covered in the earlier strings article, this is worth restating here specifically: neither indexing nor slicing ever modifies the original string. Both always return something new — a single character, or a new substring — leaving the original completely untouched.

word = "Python"
sliced = word[0:3]

print(word)     # Python — unchanged
print(sliced)   # Pyt — a separate new string
Quick example: checking for palindromes

A neat, compact use of the reversing idiom from earlier: checking whether a string reads the same forward and backward.

def is_palindrome(s):
    return s == s[::-1]

print(is_palindrome("racecar"))   # True
print(is_palindrome("python"))    # False

This works because s[::-1] produces the string reversed, and comparing it directly against the original with == tells you immediately whether the two match — no loop, no manual character-by-character comparison required.

PREVIOUSNEXT LESSON