bytearray()

A mutable byte buffer — for when bytes is not enough and you need append() or slice assignment.

Built-in function / typePython 3.0+Live demo
Common call
buf = bytearray(1024)
Returns
a mutable bytearray
Replaces
the pattern of building a new bytes object by concatenation
Watch out
bytearray(5) is FIVE zero bytes, not b"5" — same trap as bytes()
bytearray(sourcesourceThe initial data. int: number of zero bytes. Iterable of ints: those bytes. String: requires encoding.type: int | iterable | str · default: ""=..., encodingencodingWhen source is a string, the encoding to use.type: str · default: null=..., errorserrorsError handler when encoding a string.type: str · default: "strict"=...)
bytearray

Demo

Live evaluation
Try:
Inputs
sourcestrtext or comma-separated ints
encodingstrutf-8 / ascii / latin-1 (for str)
Output
bytearray('hello', 'utf-8')
'bytearray(b\'hello\')'

bytearray has the same THREE call shapes as bytes. The demo shows the constructed value in Python's bytearray(b'...') display form. In real code the difference from bytes is what you can DO with the result: bytearray supports append(), extend(), pop(), item assignment (buf[0] = 255), and slice assignment. bytes is read-only.

Parameters

NameTypeRequiredDescription
sourceint | iterable | strno ("")The initial data. int: number of zero bytes. Iterable of ints: those bytes. String: requires encoding.
encodingstrnoWhen source is a string, the encoding to use.
errorsstrno ("strict")Error handler when encoding a string.

Return value

bytearrayA MUTABLE sequence of bytes (integers 0..255). Same three call shapes as bytes: `bytearray(int)` → n zero bytes; `bytearray(iterable_of_ints)` → those bytes; `bytearray(str, encoding)` → same as str.encode. Supports item assignment and mutation methods.

Common patterns

Pre-allocated buffer for I/O
When a low-level API wants a writable buffer.
buffer = bytearray(4096)
n = sock.recv_into(buffer)
Build up incrementally
append() and extend() modify in place — no repeated reallocation.
out = bytearray()
for chunk in chunks:
    out.extend(chunk)
In-place byte manipulation
Modify individual bytes without recreating the buffer.
buf = bytearray(data)
for i in range(len(buf)):
    buf[i] ^= 0xff   # XOR each byte
Freeze to bytes when done
Convert to immutable bytes at the API boundary.
result = bytes(mutable_buf)

Examples

1. From string
bytearray("hello", "utf-8")
Returns
bytearray(b'hello')
2. From int list
bytearray([65, 66, 67])
Returns
bytearray(b'ABC')
3. Zero-init buffer
bytearray(5)
Returns
bytearray(b'\x00\x00\x00\x00\x00')
4. Empty
bytearray()
Returns
bytearray(b'')
5. Item assignment
b = bytearray(b"hello") b[0] = 72 b
Returns
bytearray(b'Hello')
6. Append
b = bytearray() b.append(65) b
Returns
bytearray(b'A')
7. Convert to bytes
bytes(bytearray(b"hi"))
Returns
b'hi'

Pitfalls

1. bytearray(5) is FIVE zero bytes — same trap as bytes()
The single most common bytearray constructor surprise. Passing an int means "that many zero bytes", not "the digit as a byte".
Assumed digit
bytearray(5)
bytearray(b'\x00\x00\x00\x00\x00')
For the digit
bytearray([5])   # bytearray(b'\x05')
bytearray(b"5")   # bytearray(b'5')
literal vs digit
2. Mutations return None; slicing returns bytes
Two subtle behaviors. Mutations (append, extend, sort, ...) return None — do not assign back. Slicing a bytearray returns a NEW bytearray, but slice assignment mutates in place.
Assigned None
buf = buf.append(65)
buf is now None
Just mutate
buf.append(65)
buf is the updated bytearray
3. Item assignment requires an int in 0..255
Setting a byte by index takes an integer. Passing a bytes-like value raises TypeError. Slice assignment DOES accept bytes-like values.
Byte-like fails
b[0] = b"H"
TypeError: 'bytes' object cannot be interpreted as an integer
Use int
b[0] = 72   # ord("H")
bytearray(b'H...')
4. bytearray is NOT hashable
Because bytearray is mutable, it cannot be a dict key or set element. Convert to bytes if you need hashability.
Not hashable
{bytearray(b"a"): 1}
TypeError: unhashable type: 'bytearray'
Freeze first
{bytes(bytearray(b"a")): 1}
{b'a': 1}

When to use

Use it
  • Pre-allocated buffers for socket / file I/O
  • Building bytes incrementally with append / extend
  • In-place byte manipulation (XOR, bit flips, byte-level transforms)
  • Any use case where you would use a bytes object but need to mutate
Reach for something else
  • Read-only data → bytes is smaller and hashable
  • Very short bytes constants → b"..." literal is clearer
  • You want the result as bytes at the end → convert with bytes(buf)
  • You need dict / set membership → not hashable, use bytes

Notes

Complexity
O(n) construction; O(1) amortized append
Return
A new bytearray object — mutable, NOT hashable
CPython impl
Objects/bytearrayobject.c :: bytearray_new
Memory
Allocates a resizable buffer with slack for growth
Thread-safe
Not safe under concurrent mutation

FAQ

bytes is IMMUTABLE and hashable — usable as a dict key or set element. bytearray is MUTABLE — supports append, extend, item and slice assignment. Both share all reading operations; bytearray adds mutation.

History

3.0
bytes and bytearray became separate types (Python 2 had only str, which behaved as bytes).