Python 创建元类以将结构解压为命名元组

Python 创建元类以将结构解压为命名元组,python,Python,我最近读了一些关于元类的SO问题,虽然它似乎不是大多数时候都需要使用的东西(包括我的问题),但我认为它对于这个案例来说会很有趣 在的python文档中,有一个名为tuple的示例: from collections import namedtuple Student = namedtuple('Student', 'name serialnum school gradelevel') Student._make(unpack('<10sHHb', record)) 从集合导入namedt

我最近读了一些关于元类的SO问题,虽然它似乎不是大多数时候都需要使用的东西(包括我的问题),但我认为它对于这个案例来说会很有趣

在的python文档中,有一个名为tuple的示例:

from collections import namedtuple
Student = namedtuple('Student', 'name serialnum school gradelevel')
Student._make(unpack('<10sHHb', record))
从集合导入namedtuple
Student=namedtuple('Student','name serialnum school gradelevel')
学生:(打开包装)是的,有可能:

from collections import namedtuple
from struct import pack, unpack

class MetaStruct(type):
    def __new__(meta, name, bases, attrs):
        nt = namedtuple(name, attrs.pop('fields'))
        struct = attrs.pop('struct')
        def factory(record):
            return nt._make(unpack(struct, record))
        return factory

class Student(object):
    __metaclass__ = MetaStruct
    fields = 'name serialnum school gradelevel'
    struct = '<10sHHb'

record = pack('<10sHHb', 'student123', 123, 456, 12)
s = Student(record)
# => Student(name='student123', serialnum=123, school=456, gradelevel=12)
从集合导入namedtuple
从结构导入包中,解压缩
类元结构(类型):
定义新(元、名称、基、属性):
nt=namedtuple(名称,attrs.pop('fields'))
struct=attrs.pop('struct')
def工厂(记录):
返回新台币(解包(结构、记录))
返回工厂
班级学生(对象):
__元类\元结构
字段='name serialnum school gradelevel'

struct='lanzz的答案非常简洁;下面是一个使用decorator的替代方法:

class Dec(object):
    def __init__(self, cls, fields=None, struct=None):
        print cls,fields,struct
        self.cls = cls
        self.nt = namedtuple(cls.__name__, fields or cls.fields)
        self.struct = struct

    def __call__(self, record):
        return self.nt._make(unpack(self.struct or self.cls.struct, record))


@Dec
class Student(object):
    fields = 'name serialnum school gradelevel'
    struct = '<10sHHb'


s = Student('abcdefghla00000')
class Dec(对象):
定义初始化(self,cls,fields=None,struct=None):
打印cls、字段、结构
self.cls=cls
self.nt=namedtuple(cls.\uuu name\uuuu、字段或cls.fields)
self.struct=struct
定义呼叫(自我,记录):
返回self.nt.\u make(解包(self.struct或self.cls.struct,记录))
@十二月
班级学生(对象):
字段='name serialnum school gradelevel'

struct='绝对是一个有趣的问题,下面是我的解决方案:

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)
导入结构
导入集合
类元结构(类型):
定义新定义(cls、clsname、bases、dct):
nt=collections.namedtuple(clsname,dct['fields'])
def新(cls,记录):
返回超级(cls,cls)。\新的(cls,*struct.unpack(dct['struct'],record))
dct.update(_new__=new)
返回超级(元结构,cls)。\uuuuu新建\uuuuuuu(cls,clsname,(nt,),dct)
班级学生(对象):
__元类\元结构
字段='name serialnum school gradelevel'

struct='我不知道你在问什么,但是如果你愿意,你可以使用
self.\uu name\uuu
来获取你正在使用的类的名称,这样你就可以在构造函数中构造
namedtuple
,而不知道你给这个类的实际名称。@2rs2ts我想通过给出它的字段和结构布局来定义一个类,这样就可以直接从其数据构造它。这样第二个块的结果与第一个块的结果相同。哦,我会使用
setattr
进行此操作。我不熟悉
struct
模块,但我会说传入结构字符串并将其解包,然后根据解包结果使用
setattr
。Rel艾德:这很聪明,但有一点需要注意,
Student
不是一个类,所以类似于
isinstance(s,Student)
将引发一个异常。这将很难诊断,您可能最好只创建一个工厂函数,而不是使用类/元类魔术。我很感兴趣,想看看我是否可以解决我上一次评论中的问题,只是添加了一个类似的答案,似乎可以解决这个问题。
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)