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?

Original source