During the initial development of the Python 3 language specification, the
core bytes type for arbitrary binary data started as the mutable type
that is now referred to as bytearray. Other aspects of operating in
the binary domain in Python have also evolved over the course of the Python
3 series.

This PEP proposes four small adjustments to the APIs of the bytes,
bytearray and memoryview types to make it easier to operate entirely
in the binary domain:

It will behave just as the current constructors behave when passed a single
integer.

The specific choice of zeros as the alternative constructor name is taken
from the corresponding initialisation function in NumPy (although, as these
are 1-dimensional sequence types rather than N-dimensional matrices, the
constructors take a length as input rather than a shape tuple)

The documentation of the ord builtin will be updated to explicitly note
that bytes.byte is the inverse operation for binary data, while chr
is the inverse operation for text data.

Behaviourally, bytes.byte(x) will be equivalent to the current
bytes([x]) (and similarly for bytearray). The new spelling is
expected to be easier to discover and easier to read (especially when used
in conjunction with indexing operations on binary sequence types).

As a separate method, the new spelling will also work better with higher
order functions like map.

This PEP proposes that bytes, bytearray and memoryview gain an
optimised iterbytes method that produces length 1 bytes objects
rather than integers:

for x in data.iterbytes():
# x is a length 1 ``bytes`` object, rather than an integer

The method can be used with arbitrary buffer exporting objects by wrapping
them in a memoryview instance first:

for x in memoryview(data).iterbytes():
# x is a length 1 ``bytes`` object, rather than an integer

For memoryview, the semantics of iterbytes() are defined such that:

memview.tobytes() == b''.join(memview.iterbytes())

This allows the raw bytes of the memory view to be iterated over without
needing to make a copy, regardless of the defined shape and format.

The main advantage this method offers over the map(bytes.byte, data)
approach is that it is guaranteed not to fail midstream with a
ValueError or TypeError. By contrast, when using the map based
approach, the type and value of the individual items in the iterable are
only checked as they are retrieved and passed through the bytes.byte
constructor.

However, this was also the case when the bytearray type was originally
designed, and the decision was made to add explicit support for it in the
type constructor. The immutable bytes type then inherited that feature
when it was introduced in PEP 3137.

This PEP isn't revisiting that original design decision, just changing the
spelling as users sometimes find the current behaviour of the binary sequence
constructors surprising. In particular, there's a reasonable case to be made
that bytes(x) (where x is an integer) should behave like the
bytes.byte(x) proposal in this PEP. Providing both behaviours as separate
class methods avoids that ambiguity.