Difference Between bytes and bytearray in Python

In Python, both bytes and bytearray are built-in types used to store raw binary data as sequences of eight-bit integers ranging from 0 to 255. The fundamental distinction between the two is mutability: a bytes object is immutable and cannot be altered after creation, whereas a bytearray is mutable and supports in-place modifications. This core difference dictates how each type handles memory allocation, performance during data manipulation, and their suitability for different programming tasks such as networking, file I/O, and cryptography.

Mutability and In-Place Modifications

The primary distinction lies in how Python handles changes to the underlying data:

# bytes example (raises TypeError on modification)
data_bytes = b"hello"
# data_bytes[0] = 106  # TypeError: 'bytes' object does not support item assignment

# bytearray example (modifies data in place)
data_array = bytearray(b"hello")
data_array[0] = 106  # ASCII for 'j'
print(data_array)    # Output: bytearray(b'jello')

Hashability and Dictionary Keys

Because bytes objects are immutable, they are hashable. This means a bytes instance can be used as a key in a dictionary or stored as an element in a set.

Conversely, because bytearray is mutable, it is unhashable. Attempting to use a bytearray as a dictionary key or inside a set will immediately raise a TypeError: unhashable type: 'bytearray'.

Memory Usage and Performance

Syntax and Initialization

A bytes object can be defined directly using literal syntax with a b prefix:

b_literal = b"example"

A bytearray does not have a dedicated literal syntax and must be created using the bytearray() constructor, which accepts an iterable of integers, a string with an explicit encoding, an existing buffer object, or an integer specifying a zero-initialized size:

ba_from_bytes = bytearray(b"example")
ba_from_size = bytearray(10)  # 10 null bytes

When to Use Each