bytes.join()
The separator is the object you call the method on, which reads backwards until it clicks. It is also the only sane way to build a large buffer from many pieces.
Demo
The separator goes BETWEEN the parts, never at the ends — so three parts get two separators. A single part gets none at all, and an empty iterable gives empty bytes rather than an error. The empty-separator case is the standard way to concatenate a list of chunks into one buffer with nothing between them.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| iterable | iterable | yes | Any iterable of bytes-like objects. A generator works; the items are consumed once. |
Return value
bytes — One bytes object with the separator placed between each item. An empty iterable gives empty bytes.
Common patterns
body = b''.join(chunks)
line = b','.join(fields)
data = b''.join(read_chunk() for _ in range(n))
Examples
Pitfalls
[b'a', b'b'].join(b',')
b','.join([b'a', b'b'])
b','.join([b'a', 'b'])
b','.join(p.encode() for p in ['a', 'b'])
buf = b'' for c in chunks: buf += c
buf = b''.join(chunks)
b'\n'.join([b'a', b'b'])
b'\n'.join([b'a', b'b']) + b'\n'
When to use
- Assembling a buffer from many chunks
- Rebuilding a delimited record after editing its fields
- Any loop that would otherwise concatenate with +=
- Two or three fixed pieces → plain + is clearer
- The parts are text → join the strings, then encode once
- You are appending repeatedly over time → bytearray
Notes
FAQ
Because join belongs to the separator type, and any iterable can supply the parts. Putting it on the list would mean every sequence type needed its own version. It reads oddly at first and then becomes second nature.
b','.join(parts)