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(Immutable): Once instantiated, individual elements cannot be reassigned, added, or removed. Any operation that appears to modify abytesobject (such as concatenation or slicing) actually allocates new memory and returns an entirely newbytesobject.bytearray(Mutable): Elements can be modified in place via index assignment or slicing. Abytearrayfunctions similarly to a standard Pythonlist, offering methods such as.append(),.extend(),.insert(),.pop(), and.reverse().
# 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
bytes: Because their size is fixed upon creation,bytesobjects require less memory overhead. Python allocates exactly the number of bytes required to hold the data plus minimal object header information.bytearray: To allow efficient appending and resizing without reallocating memory on every change,bytearrayrelies on an over-allocation strategy similar to Python lists. This introduces slightly higher baseline memory overhead per object. However, repeated mutations or appends are significantly faster on abytearraybecause they avoid repeated buffer copies.
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 bytesWhen to Use Each
Use
byteswhen:- Storing static binary data that should not change throughout program execution.
- You need hashable data for dictionary keys or set membership.
- Transmitting read-only payloads over sockets or reading fixed blocks from disk.
Use
bytearraywhen:- Building or modifying binary payloads incrementally.
- Performing in-place data transformations, such as encryption, decryption, or packet parsing.
- Implementing high-throughput I/O buffers to minimize memory allocations.