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.
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.
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())
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.