bytes() in Python 2026: Immutable Binary Sequences + Modern Use Cases & Best Practices
The built-in bytes() type creates an immutable sequence of bytes (values 0–255) — the read-only counterpart to bytearray. In 2026 it remains the standard for fixed binary data: keys, hashes, network payloads, file contents, image bytes, crypto material, and protocol messages where immutability guarantees safety and hashability.
With Python 3.12–3.14+ offering faster bytes operations, better memoryview interop, and free-threading compatibility, bytes objects are more efficient than ever in concurrent I/O, streaming, and ML binary preprocessing. This March 23, 2026 update explains how bytes() works today, creation patterns, real-world usage, performance notes, and best practices when combined with memoryview, encoding/decoding, or modern libraries.
TL;DR — Key Takeaways 2026
bytes(source)→ creates immutable bytes sequence (0–255 values)- Immutable → safe for dict keys, hashing, sharing between threads
- 2026 best practice: Prefer bytes for fixed data; use bytearray only when mutation is needed
- Main use cases: binary I/O, network protocols, crypto keys, image bytes, protocol buffers
- Zero-copy power: pair with
memoryview(bytes_obj)for fast read-only slicing - Performance: Fast creation & slicing — no allocation overhead on views
1. Basic Usage — Creating bytes Objects
# From string with encoding
b1 = bytes("Hello 2026", "utf-8")
print(b1) # b'Hello 2026'
# From list of integers (0–255)
b2 = bytes([72, 101, 108, 108, 111])
print(b2) # b'Hello'
# From bytearray (copy)
ba = bytearray(b"Mutable")
b3 = bytes(ba)
ba[0] = ord('m')
print(b3) # b'Mutable' (unchanged)
# Empty bytes
b4 = bytes() # b''
2. Real-World Patterns in 2026
Network / Protocol Message Handling
def create_message(cmd: int, payload: str) -> bytes:
header = bytes([cmd, len(payload)])
body = payload.encode("utf-8")
return header + body
msg = create_message(0x01, "status 2026")
print(msg.hex()) # 010d7374617475732032303236
Hashing & Crypto Keys (Immutable & Hashable)
import hashlib
key = bytes.fromhex("deadbeefcafebabe")
print(hash(key)) # usable as dict key
digest = hashlib.sha256(key).digest()
print(digest.hex())
Image / Binary File Read (with memoryview)
with open("image.png", "rb") as f:
data = f.read() # returns bytes
mv = memoryview(data)
header = mv[:8].tobytes()
print(header.hex()) # 89504e470d0a1a0a (PNG signature)
3. bytes vs bytearray vs Other Types – Comparison 2026
| Type | Mutable? | Hashable? | Best For |
|---|---|---|---|
| bytes | No | Yes | Immutable data, keys, hashes, protocol messages |
| bytearray | Yes | No | In-place edits, building buffers |
| numpy.ndarray (uint8) | Yes | No | Image/array processing |
| array.array("B") | Yes | No | Lightweight alternative |
4. Best Practices & Performance in 2026
- Prefer bytes for fixed, immutable binary data — safer & hashable
- Use memoryview(bytes_obj) for zero-copy read-only slicing
- Type hints 2026:
from typing import Union def process_binary(data: Union[bytes, bytearray]) -> bytes: if isinstance(data, bytearray): data = bytes(data) return data[:10] - Performance: bytes slicing is fast (C-level), but creates new objects — use memoryview for zero-copy
- Free-threading (3.14+): bytes objects are thread-safe (immutable)
Conclusion — bytes() in 2026: Immutable Binary Standard
bytes() is the default choice for any fixed binary data in Python — safe, hashable, and efficient. In 2026, use it for protocol messages, crypto keys, file contents, and immutable buffers; switch to bytearray only when mutation is required. Pair it with memoryview for zero-copy slicing and modern I/O patterns — it’s fast, reliable, and one of Python’s most important types for binary and low-level work.
Next steps:
- Convert any mutable binary code to bytes when immutability is safe