是否有一种方法可以方便地在Python中定义类c结构?我厌倦了写这样的东西:
class MyStruct():
def __init__(self, field1, field2, field3):
self.field1 = field1
self.field2 = field2
self.field3 = field3
是否有一种方法可以方便地在Python中定义类c结构?我厌倦了写这样的东西:
class MyStruct():
def __init__(self, field1, field2, field3):
self.field1 = field1
self.field2 = field2
self.field3 = field3
当前回答
使用命名元组,该元组被添加到Python 2.6标准库中的collections模块中。如果你需要支持Python 2.4,也可以使用Raymond Hettinger的命名元组配方。
它适用于基本示例,但也适用于稍后可能遇到的一些边缘情况。你上面的片段可以写成:
from collections import namedtuple
MyStruct = namedtuple("MyStruct", "field1 field2 field3")
新创建的类型可以这样使用:
m = MyStruct("foo", "bar", "baz")
你也可以使用命名参数:
m = MyStruct(field1="foo", field2="bar", field3="baz")
其他回答
你可以用元组来做很多你在C语言中使用结构体的事情(比如x,y坐标或RGB颜色)。
对于其他任何东西,你可以使用字典,或像这样的实用程序类:
>>> class Bunch:
... def __init__(self, **kwds):
... self.__dict__.update(kwds)
...
>>> mystruct = Bunch(field1=value1, field2=value2)
我认为“权威”的讨论在这里,在Python Cookbook的出版版本中。
这里的一些答案非常详尽。我找到的最简单的选项是(from: http://norvig.com/python-iaq.html):)
class Struct:
"A structure that can have any fields defined."
def __init__(self, **entries): self.__dict__.update(entries)
初始化:
>>> options = Struct(answer=42, linelen=80, font='courier')
>>> options.answer
42
添加更多的:
>>> options.cat = "dog"
>>> options.cat
dog
编辑:对不起,没有看到这个例子已经进一步。
你可以通过以下方式在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
我能想到的最干净的方法是使用一个类装饰器,它可以让你声明一个静态类,并将其重写为一个具有正常命名属性的结构体:
from as_struct import struct
@struct
class Product():
name = 'unknown product'
quantity = -1
sku = '-'
# create instance
p = Product('plush toy', sku='12-345-6789')
# check content:
p.name # plush toy
p.quantity # -1
p.sku # 12-345-6789
使用以下装饰器代码:
def struct(struct_class):
# create a new init
def struct_init(self, *args, **kwargs):
i = 0 # we really don't need enumerate() here...
for value in args:
name = member_names[i]
default_value = member_values[i]
setattr(self, name, value if value is not None else default_value)
i += 1 # ...we just need to inc an int
for key,value in kwargs.items():
i = member_names.index(key)
default_value = member_values[i]
setattr(self, key, value if value is not None else default_value)
# extract the struct members
member_names = []
member_values = []
for attr_name in dir(struct_class):
if not attr_name.startswith('_'):
value = getattr(struct_class, attr_name)
if not callable(value):
member_names.append(attr_name)
member_values.append(value)
# rebind and return
struct_class.init = struct_init
return struct_class
它的工作原理是获取类,提取字段名及其默认值,然后重写类的__init__函数,根据知道哪个参数索引映射到哪个属性名来设置self属性。