Python 3 min read

Classes

A class is a blueprint: it bundles data with the functions (methods) that work on it. Each object made from it has its own data. Inheritance lets a TempFrame reuse everything a Frame can do and add what is special about it.

The base class Frame stores the raw bytes and provides valid(). TempFrame inherits from Frame and adds celsius(); StatusFrame inherits from Frame and adds flags().
TempFrame is a Frame: it inherits valid() and adds celsius().

A class for a frame

The method __init__ runs when you create an object and stores its data on self, the object itself. Every method takes self first. START is a class attribute, shared by every frame. A subclass names its parent in brackets and inherits all of its methods.

frame_class.pyPython
import structclass Frame:    """A sensor frame: start byte, payload, 8-bit checksum."""    START = 0xAA    def __init__(self, raw: bytes):        self.raw = raw    def valid(self) -> bool:        return self.raw[0] == self.START and sum(self.raw[:-1]) & 0xFF == self.raw[-1]class TempFrame(Frame):    def celsius(self) -> float:        (raw,) = struct.unpack_from("<h", self.raw, 1)        return raw / 100f = TempFrame(bytes([0xAA, 0x29, 0x09, 0x01, 0xDD]))print(f.valid(), f.celsius())
Output
True 23.45

You create an object by calling the class like a function: TempFrame(raw). Each object keeps its own raw, so a list of frames from a capture keeps every reading separate, while all of them share the methods and START. Calling f.valid() passes f in as self for you.

Encapsulation, the Python way

Python has no private keyword. By convention, a name starting with an underscore, such as self._buffer, is internal: other code can reach it but shouldn't. That is enough for bench tools, where the aim is a clear interface (valid(), celsius()) rather than a locked one.