Creating a metaclass to unpack a struct into a namedtuple
python
Solution
Definitely an interesting problem, here is my solution:
import struct
import collections
class MetaStruct(type):
def __new__(cls, clsname, bases, dct):
nt = collections.namedtuple(clsname, dct['fields'])
def new(cls, record):
return super(cls, cls).__new__(cls, *struct.unpack(dct['struct'], record))
dct.update(__new__=new)
return super(MetaStruct, cls).__new__(cls, clsname, (nt,), dct)
class Student(object):
__metaclass__ = MetaStruct
fields = 'name serialnum school gradelevel'
struct = '<10sHHb'
record = 'raymond \x32\x12\x08\x01\x08'
s = Student(record)
The significant difference between my answer and the others is that at the end of this `Student` is still a class and `s` is an instance of `Student` (`isinstance(s, Student)` returns True). I accomplished this by having the metaclass add the namedtuple as a base class of the newly created class, with object creation of the new class (`Student.__new__`) delegated to the base class (the namedtuple).
Problem
I've recently read a few SO questions on metaclasses, and while it seems like something that's not necessary to use most of the time (including my question), I thought it'd be interesting for this case. In the python docs for struct, there is an example with namedtuple here: ``` from collections import namedtuple Student = namedtuple('Student', 'name serialnum school gradelevel') Student._make(unpack('<10sHHb', record)) ``` My question is: is it possible to create a metaclass that I could use to do part of this for me? Like my intended solution is: ``` class Student(object): __metaclass__ = ??? fields = 'name serialnum school gradelevel' struct = '<10sHHb' s = Student(record) # and give same output as the _make() call above ``` How do I do this?