创建C/C+;类结构对象的最佳方法是什么+;用python?

创建C/C+;类结构对象的最佳方法是什么+;用python?,python,struct,Python,Struct,我一直在从Matlab切换到NumPy/Scipy,我认为NumPy在很多方面都很棒 但我感到不舒服的一件事是,我在C/C++中找不到类似于struct的数据结构 例如,我可能想做以下事情: struct Parameters{ double frame_size_sec; double frame_step_sec; } 一个最简单的方法是使用字典,如下所示 parameters = {"frame_size_sec" : 0.0, "frame_step_sec", 0.0}

我一直在从Matlab切换到NumPy/Scipy,我认为NumPy在很多方面都很棒

但我感到不舒服的一件事是,我在C/C++中找不到类似于
struct
的数据结构

例如,我可能想做以下事情:

struct Parameters{
  double frame_size_sec;
  double frame_step_sec;
}
一个最简单的方法是使用字典,如下所示

  parameters = {"frame_size_sec" : 0.0, "frame_step_sec", 0.0}
但对于字典,与struct不同,可以添加任何键。我想限制钥匙

另一个选项可能是使用如下所示的类。但它也有同样类型的问题

class Parameters:
  frame_size_sec = 0.0
  frame_step_sec = 0.0
从一个线程中,我看到了一个名为namedtuple的数据结构,它看起来很棒,但最大的问题是字段是不可变的。所以它仍然和我想要的不同


总之,在python中使用类似结构的对象的最佳方式是什么?

如果不需要实际的内存布局保证,用户定义的类可以使用将其实例成员集限制为固定列表。例如:

class Parameters:  # On Python 2, class Parameters(object):, as __slots__ only applies to new-style classes
    __slots__ = 'frame_size_sec', 'frame_step_sec'
    def __init__(self, frame_size_sec=0., frame_step_sec=0.):
        self.frame_size_sec = float(frame_size_sec)
        self.frame_step_sec = float(frame_step_sec)
获取一个类,其中在初始化时,保证分配两个
float
成员,并且没有人可以(意外或故意)向该类的任何实例添加新实例属性

请阅读
\uuuuuuuuuuuuuu
文档中的注意事项;例如,在继承的情况下,如果一个超类没有定义
\uuuuu slots\uuuuu
,那么子类仍然会有
\uuuuuu dict\uuuu
,因此可以在其上定义任意属性


如果您需要内存布局保证和更严格的变量(C)类型,您会想看看,但从您所说的,听起来您只是试图强制执行一组固定的、有限的属性,而不是特定的类型或内存布局。

如果您不需要实际的内存布局保证,用户定义的类可以使用将其实例成员集限制为固定列表。例如:

class Parameters:  # On Python 2, class Parameters(object):, as __slots__ only applies to new-style classes
    __slots__ = 'frame_size_sec', 'frame_step_sec'
    def __init__(self, frame_size_sec=0., frame_step_sec=0.):
        self.frame_size_sec = float(frame_size_sec)
        self.frame_step_sec = float(frame_step_sec)
获取一个类,其中在初始化时,保证分配两个
float
成员,并且没有人可以(意外或故意)向该类的任何实例添加新实例属性

请阅读
\uuuuuuuuuuuuuu
文档中的注意事项;例如,在继承的情况下,如果一个超类没有定义
\uuuuu slots\uuuuu
,那么子类仍然会有
\uuuuuu dict\uuuu
,因此可以在其上定义任意属性


如果您需要内存布局保证和更严格的变量(C)类型,您会想看看,但从您所说的,听起来您只是试图强制执行一组固定的、有限的属性,而不是特定的类型或内存布局。

同时冒着不太像Python的风险,您可以通过子类化
dict
类并覆盖其某些方法来创建不可变字典:

def not_supported(*args, **kwargs):
        raise NotImplementedError('ImmutableDict is immutable')


class ImmutableDict(dict):
    __delitem__ = not_supported
    __setattr__ = not_supported
    update = not_supported
    clear = not_supported
    pop = not_supported
    popitem = not_supported

    def __getattr__(self, item):
        return self[item]

    def __setitem__(self, key, value):
        if key in self.keys():
            dict.__setitem__(self, key, value)
        else:
            raise NotImplementedError('ImmutableDict is immutable')
一些用法示例:

my_dict = ImmutableDict(a=1, b=2)
print my_dict['a']
>> 1
my_dict['a'] = 3 # will work, can modify existing key
my_dict['c'] = 1 # will raise an exception, can't add a new key
print my_dict.a # also works because we overwrote __getattr__ method
>> 3

冒着不是很Pythonic的风险,您可以通过子类化
dict
类并覆盖其某些方法来创建一个不可变的字典:

def not_supported(*args, **kwargs):
        raise NotImplementedError('ImmutableDict is immutable')


class ImmutableDict(dict):
    __delitem__ = not_supported
    __setattr__ = not_supported
    update = not_supported
    clear = not_supported
    pop = not_supported
    popitem = not_supported

    def __getattr__(self, item):
        return self[item]

    def __setitem__(self, key, value):
        if key in self.keys():
            dict.__setitem__(self, key, value)
        else:
            raise NotImplementedError('ImmutableDict is immutable')
一些用法示例:

my_dict = ImmutableDict(a=1, b=2)
print my_dict['a']
>> 1
my_dict['a'] = 3 # will work, can modify existing key
my_dict['c'] = 1 # will raise an exception, can't add a new key
print my_dict.a # also works because we overwrote __getattr__ method
>> 3

这对字段集没有类范围的限制,它只限制您在实例化时定义字段(OP明确表示他不想要不可变的字段)。@ShadowRanger我编辑了我的答案,允许修改现有键,但不允许添加新键,这正是OP想要的。可能想要
\uuuuu setattr\uuuuu=\uuuuu setitem\uuuuuu
所以
my_dict.a=3
工作时不会太明显地暴露“它实际上是一个字典,而不是一个对象”的东西。这对字段集没有类范围的限制,它只限制您在实例化时定义字段(OP明确表示他不想要不可变的字段)。@ShadowRanger我已经编辑了我的答案,允许修改现有的键,但不允许添加新的键,这正是OP想要的。可能需要
\uuuuuuuSetAttr\uuuu=\ uuuuuuuuuuSetItem\uuuuuuuu
所以
我的dict.a=3
可以在不公开密码的情况下工作“它实际上是一个字典,而不是一个对象”这一点太明显了。仅供参考,使用
\uuuuuu插槽\uuuuuuuuuuuu
确实有一些优势。从CPU角度看,它基本上是不相关的,但它显著降低了每个实例的内存成本。在Python 3.4(64位)上,对于一个2变量的实例,对象结构的开销加上它的
\uuuuu dict\uuu
的结构是152字节,而对于对象结构(没有
\uuuu dict\uuu
),如果它是用
\uu slots\uuu
定义的,则是56字节。Python 2上的差异甚至更大(因为Python 2缺少共享密钥字典;两种情况下的基本对象结构都使用64个字节,但是
\uuu dict\uuu
所需的w/o
\uu slots\uuu
最多占用344个字节).FYI,使用
\uuuuuu slots\uuuuu
确实有一些优势。就CPU而言,这基本上是不相关的,但它显著降低了每个实例的内存成本。在Python 3.4(64位)上,对于一个2变量实例,对象结构的开销加上其
\uuuuuu dict\uuu
的结构是152字节,而对象结构的开销是56字节(如果定义为
\uuuuuuuuuuuuuuuuuuuuuuuuu
,则没有
\uuuuuuuuuuuuuuuuuuuu
)。Python2上的差异甚至更为极端(因为Python2缺少共享键字典;两种情况下的基本对象结构都使用64字节,但
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
所需的w/o
最多占用344字节)。