The slice() built-in function returns a reusable slice object representing the set of indices specified by range(start, stop, step).
First-Class Slices & Programmatic Indexing: While the standard colon notation sequence[start:stop:step] is convenient for static code, slice() creates first-class objects that can be assigned to constants, passed to functions, and reused across multiple lists, tuples, or strings. You can inspect bound index ranges using range(), or convert slice representations with repr().
The slice() constructor accepts either one argument (as stop) or up to three arguments:
# Formal signatures of built-in slice()
slice_obj = slice(stop)
slice_obj = slice(start, stop[, step])
| Argument | Type | Default | Description & Operational Rule |
|---|---|---|---|
start |
int or None |
None (0) |
Starting index of the slice (inclusive). |
stop |
int or None |
Required | Stopping index of the slice (exclusive; stops before this index). |
step |
int or None |
None (1) |
Increment interval between indices. Can be negative for reverse slicing. |
When given a single argument, it represents stop. When given two or three, they map to start, stop, and step:
# 1. Creating slice objects with 1, 2, or 3 arguments
s1 = slice(4) # stop=4, start=None, step=None
s2 = slice(2, 6) # start=2, stop=6, step=None
s3 = slice(1, 8, 2) # start=1, stop=8, step=2
print("Slice 1:", s1, "| Attributes:", s1.start, s1.stop, s1.step)
print("Slice 2:", s2, "| Attributes:", s2.start, s2.stop, s2.step)
print("Slice 3:", s3, "| Attributes:", s3.start, s3.stop, s3.step)Terminal Output:
Slice 1: slice(None, 4, None) | Attributes: None 4 None
Slice 2: slice(2, 6, None) | Attributes: 2 6 None
Slice 3: slice(1, 8, 2) | Attributes: 1 8 2
Slice objects can be reused across different data structures supporting sequence indexing:
# 2. Applying slice objects across lists, tuples, and strings
items = [10, 20, 30, 40, 50, 60, 70]
text = "plus2net_python"
coords = (1, 2, 3, 4, 5, 6)
even_steps = slice(0, None, 2)
middle_three = slice(2, 5)
print("List sliced: ", items[even_steps])
print("String sliced:", text[middle_three])
print("Tuple sliced: ", coords[middle_three])Terminal Output:
List sliced: [10, 30, 50, 70]
String sliced: us2
Tuple sliced: (3, 4, 5)
Negative indices count backward from the end of the sequence, and negative step values reverse direction:
# 3. Negative indices and reverse step slicing
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# Negative start and stop
tail_slice = slice(-4, -1)
print("Negative indices [-4:-1]:", numbers[tail_slice])
# Reversing sequences with step=-1
reverse_slice = slice(None, None, -1)
print("Reversed list: ", numbers[reverse_slice])
# Stepping backward from index 6 to 1
backward_slice = slice(6, 1, -2)
print("Backward step (6 to 1): ", numbers[backward_slice])Terminal Output:
Negative indices [-4:-1]: [6, 7, 8]
Reversed list: [9, 8, 7, 6, 5, 4, 3, 2, 1]
Backward step (6 to 1): [7, 5, 3]
The slice.indices(length) method calculates the exact concrete (start, stop, step) tuple for a sequence of the given length, resolving negative offsets and clipping out-of-bounds bounds:
# 4. Using slice.indices(length) to normalize bounds
# Normalizes slice bounds against a specific sequence length
s = slice(-5, None, 2)
sequence_len = 10
start, stop, step = s.indices(sequence_len)
print(f"Normalized for length {sequence_len} -> start={start}, stop={stop}, step={step}")
# Use generated indices directly in range()
extracted = [sequence_len]
print("Index range elements: ", list(range(start, stop, step)))Terminal Output:
Normalized for length 10 -> start=5, stop=10, step=2
Index range elements: [5, 7, 9]
Mutable sequences like lists support slice replacement and slice deletion:
# 5. In-place slice assignment and deletion on mutable sequences
data = [10, 20, 30, 40, 50, 60]
# Replace elements using slice assignment
data[slice(1, 3)] = [99, 88]
print("After slice assignment:", data)
# Delete elements using slice deletion
del data[slice(0, None, 2)]
print("After slice deletion: ", data)Terminal Output:
After slice assignment: [10, 99, 88, 40, 50, 60]
After slice deletion: [99, 40, 60]
Named slice objects make fixed-width text parsing readable and maintainable:
# 6. Production Recipe: Fixed-Width File & Record Parser
# Named reusable slice objects create self-documenting parsing logic
RECORD_ID = slice(0, 6)
FIRST_NAME = slice(6, 16)
DEPARTMENT = slice(16, 26)
SALARY_USD = slice(26, 34)
raw_records = [
"EMP001Alexander Engineering85000",
"EMP002Beatrice Marketing 72000",
"EMP003CatherineOperations68000"
]
parsed_roster = []
for row in raw_records:
employee = {
"id": row[RECORD_ID].strip(),
"name": row[FIRST_NAME].strip(),
"dept": row[DEPARTMENT].strip(),
"salary": int(row[SALARY_USD].strip())
}
parsed_roster.append(employee)
for emp in parsed_roster:
print(f"{emp['id']} | {emp['name']:<10} | {emp['dept']:<12} | USD {emp['salary']}")Terminal Output:
EMP001 | Alexander | Engineering | USD 85000
EMP002 | Beatrice | Marketing | USD 72000
EMP003 | Catherine | Operations | USD 68000
Slicing requires subscriptable sequences. Unordered collections like sets do not support indexing:
# 7. Common traps: Unsubscriptable collections and off-by-one errors
# Trap 1: Slicing sets raises TypeError (sets are unordered and unindexed)
try:
number_set = {10, 20, 30, 40}
_ = number_set[slice(0, 2)]
except TypeError as err:
print("Set slice error: ", err)
# Trap 2: Empty slice when step direction contradicts start/stop
empty_result = [1, 2, 3, 4, 5][slice(4, 1, 1)] # step is +1, but start > stop
print("Contradictory step: ", empty_result)Terminal Output:
Set slice error: 'set' object is not subscriptable
Contradictory step: []
Deepen your hands-on mastery of slice objects, index normalization, and fixed-width parsing in our interactive companion Jupyter Notebook:
Explore interactive code cells, test negative step slicing, experiment with slice.indices(), and run self-validating assertions.
Run these unit checks directly in Python or your local environment to verify slice() mechanics:
# 8. Self-verifying unit test suite for slice()
# Test 1: Slice constructor attributes
s = slice(1, 10, 2)
assert (s.start, s.stop, s.step) == (1, 10, 2)
# Test 2: Sequence slicing
data = [0, 1, 2, 3, 4, 5]
assert data[slice(2, 5)] == [2, 3, 4]
# Test 3: Reversal slice
assert "hello"[slice(None, None, -1)] == "olleh"
# Test 4: indices() method normalization
start, stop, step = slice(-3, None).indices(6)
assert (start, stop, step) == (3, 6, 1)
# Test 5: In-place slice mutation
nums = [1, 2, 3, 4]
nums[slice(1, 3)] = [8, 9]
assert nums == [1, 8, 9, 4]
print("All slice() unit assertions successfully verified!")Terminal Output:
All slice() unit assertions successfully verified!
slice() creates a reusable, named object that can be stored in constants, passed to functions, and applied consistently across multiple sequences.
No. Sets and dictionaries are unordered mappings and do not support indexing, raising TypeError: 'set' object is not subscriptable.
It converts arbitrary slice parameters into concrete non-negative (start, stop, step) integers appropriate for a sequence of the specified length.
In standard Python lists, tuples, and strings, slicing creates a shallow copy. In third-party libraries like NumPy, slicing returns a memory view.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.