Anik Sikder
Technical Writing/python/what-is-a-sequence-in-programming
article.sh

$ open article

python

What Is a Sequence in Programming? Understanding Indexing, Slicing, and Custom Sequences

10 min readSeptember 14, 2025
Python Sequence, Indexing, and Slicing Visualization

Hey developers! 👋

Have you ever wondered:

  • Why arrays, lists, and strings start counting at 0 instead of 1?
  • Why Python can magically reverse a list using [::-1]?
  • Why strings, tuples, lists, and ranges all behave so similarly?

The answer lies in one of the most fundamental concepts in programming:

Sequences

Sequences are everywhere.

Every time you loop through a list, access a character in a string, slice an array, or iterate over a range, you're working with a sequence.

Understanding sequences deeply helps you write cleaner code, understand language internals, and become much more comfortable with data structures.

Today we'll explore:

  • What sequences really are
  • Why indexing starts at 0
  • How slicing works behind the scenes
  • Shallow vs deep copying
  • Building custom sequence classes
  • Using Python's Sequence abstract base class
  • Practical examples and best practices

Ready?

Let's dive in. 🚀

What Is a Sequence?

At its core, a sequence is simply:

An ordered collection of elements that can be accessed by position.

A sequence guarantees:

  • Order
  • Index-based access
  • Iteration support

Think of a train.

code
🚂 🚃 🚃 🚃 🚃

Each carriage occupies a specific position.

You can access:

code
Position 0
Position 1
Position 2
Position 3

in a predictable order.

That's exactly how sequences behave.

Common Sequence Types in Python

Python includes several built-in sequence types.

Lists

Mutable sequences.

code
numbers = [1, 2, 3, 4]

You can modify them:

code
numbers.append(5)

Tuples

Immutable sequences.

code
coordinates = (10, 20)

Once created, they cannot be changed.

Strings

Sequences of characters.

code
name = "Python"

Access individual characters:

code
print(name[0])

Output:

code
P

Range Objects

Efficient numeric sequences.

code
range(5)

Produces:

code
0, 1, 2, 3, 4

without storing every value in memory.

Sequences in Other Languages

The concept exists everywhere.

JavaScript

code
const numbers = [1, 2, 3];
const text = "hello";

Arrays and strings behave as sequences.

Java

code
int[] numbers = {1, 2, 3};
ArrayList<Integer> list = new ArrayList<>();

C and C++

code
int numbers[3] = {1, 2, 3};

Arrays are the most fundamental sequence structures.

The idea remains the same across languages:

code
Ordered elements
+ Position-based access

Why Does Indexing Start at 0?

This question has confused generations of developers.

At first glance:

code
1, 2, 3, 4...

feels more natural than:

code
0, 1, 2, 3...

But computers have a very practical reason.

The Low-Level Explanation

Consider an array in C:

code
int arr[] = {10, 20, 30};

Internally, the array name is essentially a pointer to the first element.

When you write:

code
arr[0]

the compiler interprets it as:

code
*(arr + 0)

Meaning:

code
Value at memory address
+ offset 0

Similarly:

code
arr[1]

becomes:

code
*(arr + 1)

and:

code
arr[2]

becomes:

code
*(arr + 2)

No extra calculations required.

The index directly represents the offset from the starting address.

Why Not Start at 1?

Suppose indexing started at 1.

Then:

code
First element → index 1

Internally the computer would need:

code
actual_position = index - 1

for every lookup.

That extra adjustment would happen constantly.

Programming languages adopted 0-based indexing because it aligns perfectly with memory addressing.

Benefits of 0-Based Indexing

Faster Calculations

Offsets map directly to memory locations.

Simpler Slicing

Consider:

code
numbers = [10, 20, 30, 40]

Length:

code
len(numbers)

returns:

code
4

Last valid index:

code
4 - 1 = 3

which matches:

code
numbers[3]

perfectly.

Consistency

Many data structures use similar offset-based calculations:

  • Arrays
  • Heaps
  • Buffers
  • Strings

Everything remains mathematically consistent.

A Real-World Analogy

Imagine standing at the entrance of a movie theater.

Your current position is:

code
0 steps away

The first seat is right there.

No movement required.

Computers think similarly.

The first element exists:

code
0 positions away

from the beginning.

Simple.

Efficient.

Logical.

Understanding Python Indexing

Basic indexing:

code
letters = ["A", "B", "C", "D"]

print(letters[0])

Output:

code
A

Negative indexing works too:

code
print(letters[-1])

Output:

code
D

Python counts backward from the end.

Internally:

code
-1 → last element
-2 → second-to-last

and so on.

Python Slicing: A Developer Superpower

One of Python's most elegant features is slicing.

Example:

code
numbers = [10, 20, 30, 40, 50]

Basic Slice

code
numbers[1:4]

Output:

code
[20, 30, 40]

Omitted Start

code
numbers[:3]

Output:

code
[10, 20, 30]

Steps

code
numbers[::2]

Output:

code
[10, 30, 50]

Reverse

code
numbers[::-1]

Output:

code
[50, 40, 30, 20, 10]

One of Python's most beloved tricks.

How Slicing Works

General syntax:

code
sequence[start:stop:step]

Start

Where iteration begins.

Stop

Where iteration ends.

Not included.

Step

How much to move each iteration.

Example:

code
numbers[0:5:2]

Meaning:

code
Start at 0
Stop before 5
Move by 2

Result:

code
[10, 30, 50]

Why the Stop Value Is Exclusive

Many beginners ask:

Why doesn't Python include the stop value?

Because exclusive ranges simplify calculations.

Example:

code
numbers[0:3]

contains:

code
3 elements

because:

code
3 - 0 = 3

No special rules required.

This design appears throughout Python.

Copying Sequences Correctly

A common task:

code
original = [1, 2, 3]

Create a copy.

Using Slicing

code
copy1 = original[:]

Using Constructor

code
copy2 = list(original)

Using Copy Method

code
copy3 = original.copy()

All create shallow copies.

What Is a Shallow Copy?

Consider:

code
nested = [[1, 2], [3, 4]]

copy_list = nested.copy()

Modify:

code
nested[0][0] = 999

Now:

code
print(copy_list)

Output:

code
[[999, 2], [3, 4]]

Why?

Because only the outer list was copied.

The inner lists are still shared.

Deep Copies

For completely independent copies:

code
import copy

nested = [[1, 2], [3, 4]]

deep_copy = copy.deepcopy(nested)

Modify:

code
nested[0][0] = 999

Now:

code
print(deep_copy)

Output:

code
[[1, 2], [3, 4]]

The nested structures remain independent.

Building Your Own Sequence

One of Python's coolest features is that you can create custom sequence types.

Example:

code
class RepeatedSequence:
    def __init__(self, value, count):
        self.value = value
        self.count = count

    def __len__(self):
        return self.count

    def __getitem__(self, index):
        if isinstance(index, slice):
            start, stop, step = index.indices(self.count)

            return [
                self.value
                for _ in range(start, stop, step)
            ]

        if index < 0:
            index += self.count

        if 0 <= index < self.count:
            return self.value

        raise IndexError("Index out of range")

    def __repr__(self):
        return str([self.value] * self.count)

Trying It Out

code
seq = RepeatedSequence("🍕", 5)

Indexing:

code
print(seq[2])

Output:

code
🍕

Slicing:

code
print(seq[:3])

Output:

code
['🍕', '🍕', '🍕']

Length:

code
print(len(seq))

Output:

code
5

The object behaves like a real sequence.

Using collections.abc.Sequence

Python provides a professional shortcut.

Instead of implementing everything yourself:

code
from collections.abc import Sequence

Create:

code
class MySeq(Sequence):
    def __init__(self, data):
        self.data = data

    def __getitem__(self, index):
        return self.data[index]

    def __len__(self):
        return len(self.data)

That's it.

What Do You Get for Free?

By implementing only:

code
__getitem__()
__len__()

Python automatically provides:

code
__contains__()
__iter__()
count()
index()

and other sequence behaviors.

This is a great example of Python's powerful abstract base classes.

Sequence Thinking: A Useful Mental Model

Think of a sequence as:

code
Ordered Data + Position

If position matters:

code
Sequence

If position doesn't matter:

code
Set

Understanding this distinction helps you choose the right data structure.

TL;DR Quick Recap

  • Sequences are ordered collections of elements.
  • Lists, tuples, strings, and ranges are sequences.
  • Indexing starts at 0 because it matches memory offsets.
  • Negative indexes count backward from the end.
  • Python slicing uses start:stop:step.
  • The stop value is exclusive.
  • Shallow copies duplicate containers but share nested objects.
  • Deep copies recursively duplicate everything.
  • Custom sequences can be built using __getitem__ and __len__.
  • collections.abc.Sequence provides many sequence features automatically.

Final Thoughts: Sequences Are Everywhere 🧠

Sequences may seem like a beginner topic.

They're not.

They sit at the foundation of countless programming concepts:

  • Arrays
  • Strings
  • Buffers
  • Database rows
  • Collections
  • Iterators
  • Data pipelines

Understanding how indexing, slicing, and sequence behavior work gives you a deeper appreciation for how programming languages are designed.

And once you truly understand why indexing starts at 0, you'll stop fighting it and start seeing the elegance behind it.

A Little Python Joke to End On 😄

Why did the sequence start counting from zero?

Because it didn't want to waste an index on unnecessary introductions.


Frequently Asked Questions

What is a sequence in programming?

A sequence is an ordered collection of elements that supports indexing and iteration.

Examples include:

  • Lists
  • Tuples
  • Strings
  • Arrays
  • Ranges

Why does indexing start at 0?

Because indexes represent offsets from the starting memory address.

The first element is located:

code
0 positions away

from the beginning.


What are examples of Python sequences?

Python sequence types include:

code
list
tuple
str
range
bytes
bytearray

Each stores elements in a specific order.


What is slicing?

Slicing extracts part of a sequence.

Syntax:

code
sequence[start:stop:step]

Example:

code
numbers[1:4]

returns elements from index 1 up to (but not including) index 4.


Why is the stop index excluded?

Because exclusive boundaries make calculations simpler.

The slice length becomes:

code
stop - start

without special adjustments.


What is the difference between shallow and deep copy?

Shallow copy:

code
copy.copy(obj)

copies only the outer container.

Deep copy:

code
copy.deepcopy(obj)

recursively copies nested objects as well.


What methods are required for a custom sequence?

Typically:

code
__getitem__()
__len__()

These allow indexing and length operations.


What is collections.abc.Sequence?

It is an abstract base class that provides many sequence behaviors automatically when you implement:

code
__getitem__()
__len__()

Why does [::-1] reverse a sequence?

Because:

code
step = -1

tells Python to iterate backward through the sequence.


When should I use a sequence?

Use a sequence whenever:

  • Order matters
  • Position matters
  • Iteration is required
  • Elements need index-based access

Key Takeaways

  • Sequences are ordered collections with positional access.
  • Python provides lists, tuples, strings, and ranges as built-in sequences.
  • Zero-based indexing comes directly from memory addressing principles.
  • Slicing is a powerful mechanism for extracting and transforming data.
  • Shallow and deep copies behave very differently with nested structures.
  • Custom sequence classes are easy to build.
  • collections.abc.Sequence offers many sequence features automatically.
  • Understanding sequences improves your grasp of programming fundamentals and data structures.

If you found this helpful, share it with another developer and follow for more Python deep dives, language internals, software architecture discussions, and programming fundamentals. 🚀


About the Author

Anik Sikder is a Software Engineer specializing in Backend Development, Python, Django, FastAPI, DevOps, Cloud Infrastructure, and Software Architecture.

He writes about Python internals, software engineering fundamentals, system design, scalable backend systems, and modern software architecture.

$ tags

pythonsequencesdata-structuresindexingslicingpython-basicscollectionsprogramming-fundamentalssoftware-engineering

$ ls related_articles

status: end_of_file