是否有一种方法可以方便地在Python中定义类c结构?我厌倦了写这样的东西:

class MyStruct():
    def __init__(self, field1, field2, field3):
        self.field1 = field1
        self.field2 = field2
        self.field3 = field3

当前回答

你可以通过以下方式在python中访问C-Style struct。

class cstruct:
    var_i = 0
    var_f = 0.0
    var_str = ""

如果你只想使用cstruct的对象

obj = cstruct()
obj.var_i = 50
obj.var_f = 50.00
obj.var_str = "fifty"
print "cstruct: obj i=%d f=%f s=%s" %(obj.var_i, obj.var_f, obj.var_str)

如果你想创建一个cstruct对象的数组

obj_array = [cstruct() for i in range(10)]
obj_array[0].var_i = 10
obj_array[0].var_f = 10.00
obj_array[0].var_str = "ten"

#go ahead and fill rest of array instaces of struct

#print all the value
for i in range(10):
    print "cstruct: obj_array i=%d f=%f s=%s" %(obj_array[i].var_i, obj_array[i].var_f, obj_array[i].var_str)

注意: 请使用你的struct名称,而不是'cstruct'名称 请定义结构的成员变量,而不是var_i, var_f, var_str。

其他回答

我认为Python结构字典适合这个需求。

d = dict{}
d[field1] = field1
d[field2] = field2
d[field2] = field3

下面结构的解决方案是受namedtuple实现和前面一些答案的启发。然而,与namedtuple不同的是,它的值是可变的,但就像c风格的结构体在名称/属性中是不可变的,而普通的类或dict不是。

_class_template = """\
class {typename}:
def __init__(self, *args, **kwargs):
    fields = {field_names!r}

    for x in fields:
        setattr(self, x, None)            

    for name, value in zip(fields, args):
        setattr(self, name, value)

    for name, value in kwargs.items():
        setattr(self, name, value)            

def __repr__(self):
    return str(vars(self))

def __setattr__(self, name, value):
    if name not in {field_names!r}:
        raise KeyError("invalid name: %s" % name)
    object.__setattr__(self, name, value)            
"""

def struct(typename, field_names):

    class_definition = _class_template.format(
        typename = typename,
        field_names = field_names)

    namespace = dict(__name__='struct_%s' % typename)
    exec(class_definition, namespace)
    result = namespace[typename]
    result._source = class_definition

    return result

用法:

Person = struct('Person', ['firstname','lastname'])
generic = Person()
michael = Person('Michael')
jones = Person(lastname = 'Jones')


In [168]: michael.middlename = 'ben'
Traceback (most recent call last):

  File "<ipython-input-168-b31c393c0d67>", line 1, in <module>
michael.middlename = 'ben'

  File "<string>", line 19, in __setattr__

KeyError: 'invalid name: middlename'

我发现做到这一点的最好方法是使用自定义字典类,如本文所述:https://stackoverflow.com/a/14620633/8484485

如果需要iPython自动补全支持,只需像这样定义dir()函数:

class AttrDict(dict):
    def __init__(self, *args, **kwargs):
        super(AttrDict, self).__init__(*args, **kwargs)
        self.__dict__ = self
    def __dir__(self):
        return self.keys()

然后像这样定义你的伪结构(这个是嵌套的)

my_struct=AttrDict ({
    'com1':AttrDict ({
        'inst':[0x05],
        'numbytes':2,
        'canpayload':False,
        'payload':None
    })
})

然后你可以像这样访问my_struct中的值:

打印(my_struct.com1.inst)

= > [5]

你可以通过以下方式在python中访问C-Style struct。

class cstruct:
    var_i = 0
    var_f = 0.0
    var_str = ""

如果你只想使用cstruct的对象

obj = cstruct()
obj.var_i = 50
obj.var_f = 50.00
obj.var_str = "fifty"
print "cstruct: obj i=%d f=%f s=%s" %(obj.var_i, obj.var_f, obj.var_str)

如果你想创建一个cstruct对象的数组

obj_array = [cstruct() for i in range(10)]
obj_array[0].var_i = 10
obj_array[0].var_f = 10.00
obj_array[0].var_str = "ten"

#go ahead and fill rest of array instaces of struct

#print all the value
for i in range(10):
    print "cstruct: obj_array i=%d f=%f s=%s" %(obj_array[i].var_i, obj_array[i].var_f, obj_array[i].var_str)

注意: 请使用你的struct名称,而不是'cstruct'名称 请定义结构的成员变量,而不是var_i, var_f, var_str。

有一个python包正是用于此目的。看到cstruct2py

cstruct2py是一个纯python库,用于从C代码生成python类,并使用它们来打包和解包数据。该库可以解析C头文件(结构体、联合、枚举和数组声明),并在python中模拟它们。生成的python类可以解析和打包数据。

例如:

typedef struct {
  int x;
  int y;
} Point;

after generating pythonic class...
p = Point(x=0x1234, y=0x5678)
p.packed == "\x34\x12\x00\x00\x78\x56\x00\x00"

如何使用

首先,我们需要生成python结构体:

import cstruct2py
parser = cstruct2py.c2py.Parser()
parser.parse_file('examples/example.h')

现在我们可以从C代码中导入所有的名称:

parser.update_globals(globals())

我们也可以直接这样做:

A = parser.parse_string('struct A { int x; int y;};')

使用C代码中的类型和定义

a = A()
a.x = 45
print a
buf = a.packed
b = A(buf)
print b
c = A('aaaa11112222', 2)
print c
print repr(c)

输出将是:

{'x':0x2d, 'y':0x0}
{'x':0x2d, 'y':0x0}
{'x':0x31316161, 'y':0x32323131}
A('aa111122', x=0x31316161, y=0x32323131)

克隆

对于克隆cstruct2py运行:

git clone https://github.com/st0ky/cstruct2py.git --recursive