c-types Structure and equality with bytes/bytearray

Eryk Sun eryksun at gmail.com
Thu Apr 29 17:56:14 EDT 2021


On 4/26/21, Michael Hull <mikehulluk at gmail.com> wrote:
>
> my understanding was that `bytes` and `bytearray` would normally
> be expected to work quite interchangeably with each other?

bytearray.__eq__() is more flexible:

    >>> i = Int16(first=65, second=66)
    >>> bytearray(i).__eq__(i)
    True

    >>> i.__eq__(bytearray(i))
    NotImplemented
    >>> i.__eq__(bytes(i))
    NotImplemented
    >>> bytes(i).__eq__(i)
    NotImplemented

When in doubt, read the source code. In bytearray_richcompare() in
Objects/bytearrayobject.c, the comparison begins by using the buffer
protocol to get comparable byte strings. ctypes data types support the
buffer protocol, so this works well. On the other hand,
bytes_richcompare() in Objects/bytesobject.c does not use the buffer
protocol but instead requires the other object to be a bytes object.

In Python 3.3+, you can force the comparison to use the buffer
protocol via memoryview(). For example:

    >>> memoryview(i).cast('B') == bytes(i)
    True
    >>> memoryview(i).cast('B') == bytearray(i)
    True

The cast() to "B" (unsigned char) is required because views of ctypes
data objects include their format:

    >>> memoryview(i).format
    'T{<b:first:<b:second:}'
    >>> memoryview(i).cast('B').format
    'B'


More information about the Python-list mailing list