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

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

当前回答

这里的一些答案非常详尽。我找到的最简单的选项是(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

编辑:对不起,没有看到这个例子已经进一步。

其他回答

这里的一些答案非常详尽。我找到的最简单的选项是(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

编辑:对不起,没有看到这个例子已经进一步。

一本字典怎么样?

就像这样:

myStruct = {'field1': 'some val', 'field2': 'some val'}

然后你可以使用这个来操作值:

print myStruct['field1']
myStruct['field2'] = 'some other values'

值不一定是字符串。它们可以是其他任何物体。

我在这里没有看到这个答案,所以我想我将添加它,因为我现在正在学习Python,并且刚刚发现它。Python教程(在本例中是Python 2)给出了以下简单而有效的示例:

class Employee:
    pass

john = Employee()  # Create an empty employee record

# Fill the fields of the record
john.name = 'John Doe'
john.dept = 'computer lab'
john.salary = 1000

也就是说,创建一个空类对象,然后实例化,动态添加字段。

这样做的好处是非常简单。缺点是它不是特别自记录的(在类“定义”中没有列出预期的成员),并且未设置字段在访问时可能会导致问题。这两个问题可以通过以下方法解决:

class Employee:
    def __init__ (self):
        self.name = None # or whatever
        self.dept = None
        self.salary = None

现在,您至少可以一目了然地看到程序将期望哪些字段。

两者都很容易打错别字,约翰。Slarly = 1000将成功。不过,它还是有效的。

我发现做到这一点的最好方法是使用自定义字典类,如本文所述: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]

我能想到的最干净的方法是使用一个类装饰器,它可以让你声明一个静态类,并将其重写为一个具有正常命名属性的结构体:

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属性。