I have a class for decoding binary data using struct and storing in a NamedTuple as below:
class HEADER1(NamedTuple):
name: str
u2: int
tracetime: int
u4: int
u5: int
u6: int
u7: int
struct = Struct('<8s6L')
@classmethod
def unpack(cls, data):
return cls(*cls.struct.unpack(data))
This works without issue and I can use as follows:
h = HEADER1.unpack(b'svpt_str\x03\x01\x00\x00\xae\xa6i_\xd0\x03\xfe3\x00\x00\x00\x00P\xa0\xdc3\x00\x00\x00\x00')
However if I try to change it to inherit the classmethod as follows it fails:
class NamedTupleUnpack(NamedTuple):
struct = Struct('x')
@classmethod
def unpack(cls, data):
return cls(*cls.struct.unpack(data))
class HEADER1(NamedTupleUnpack):
name: str
u2: int
tracetime: int
u4: int
u5: int
u6: int
u7: int
struct = Struct('<8s6L')
Then it errors with TypeError: __new__() takes 1 positional argument but 8 were given.
I understand there are issues with inheriting from NamedTuple but wondered if there is a work around?
EDIT: as hinted by others below it looks like dataclasses are the way to go: A way to subclass NamedTuple for purposes of typechecking
typing.NamedTupledoesn't provide the feature you want, because adding fields to a subclass of a namedtuple class conflicts with the design intent of namedtuples.The design intent is that if
Foois a namedtuple class withnfields, instances ofFooshould be and behave liken-element tuples. For example, ifn==3, then you should be able to take an arbitrary instance ofFooand doAdding fields breaks this. If you could create a subclass
class Bar(Foo)with a fourth field, then instances ofBarwould be instances ofFoofor which you could not doYour
NamedTupleUnpackis a namedtuple class with 0 fields. You cannot add fields in theHEADER1subclass.You should probably use a regular class, or
dataclasses, or putunpackin a mixin.