Chinaunix首页 | 论坛 | 博客
  • 博客访问: 19087
  • 博文数量: 9
  • 博客积分: 1436
  • 博客等级: 上尉
  • 技术积分: 100
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-27 10:07
文章分类

全部博文(9)

文章存档

2011年(1)

2009年(8)

我的朋友
最近访客

分类: Python/Ruby

2009-05-31 11:18:38

【转载请注明来自SimuWorld.linkka.com】

很多时候我都遇到需要把一些C或者C++的程序转换成Python,或者在制作Python程序时候需要创建和C/C++程序中对应的数据结构。
例如,我的C程序中有这样一个结构(名字叫HEADER):

  1. struct HEADER
  2. {
  3. int version;
  4. double var;
  5. char * desc;
  6. };

现在我在Python中也需要使用这个结构(例如,这是一个二进制文件的头信息,我需要读取这个二进制文件;或者这个struct中的信息我在python程序中也需要保留)。

当然Python是无所不能的,你可以有无数种方式来生成并存储这些数据。最简单的,你可以创建一个列表或者dict,很轻松就可以完成任务。但是这里有一个更简便也灵活得多的方法,这得益于我参考互联网上的相关文档并加上一些自己的思考。

具体做法是创建一个python类,并利用python类自带的字典属性来保存数据。因此我们不需要显示地创建一个词典。看:

  1. class Header:
  2. def __init__(self,**data)
  3. self.__dict__.update(data)

对就是这些了,就是这么简单。解释一下细节:
首先,这个类是一个python的老式类(具体参见下文),创建时候系统给他创建了一个内置的dict对象,可以通过self.__dict__来访问到。
__init__这个函数是这个类实例化时一定会呼叫的函数,所以我们加了一个参数data给他,来传递我们要存储的所有数据。
data前面的两个星号意思是我们给他的所有data都会被组合成一个dict对象传给函数,data中数据的个数是任意多的。
update函数的调用保证了在我们生成这个类实例的时候,这个内置字典会记录我们送给他的所有参数。

看看用法吧:
1. 实例化

  1. >>> h=Header(version=var1, var=var2, desc="something")

2. 看看那些结构值都存储好没有:
  1. >>> h.version
  2. var1
  3. >>> h.var
  4. var2
  5. >>> h.desc
  6. something

哈,没问题哦,就像使用C结构一样容易。 至此好像任务已经完成了,但是稍等还有一点问题,
如果我们需要给这个存储的“结构”添加点成员怎么做?

太容易不过了,因为我们把数据都存放在一个python类的字典对象中,这比直接存储在一个独立的dict对象中要好。
为什么呢?好处是我们可以随时给一个不存在的类属性分配值,这个类属性会自动在类的内置词典中创建。看:
刚才那个类实例h是没有叫 any 这个名字的‘属性’的,也就是
>>> h.any 没有值
但是我们可以简单的在h创建以后加入它,只要这样
>>> h.any = "anything"
OK, 以后你就可以使用h.any了,很灵活吧。

可是这种灵活性有的时候并不是我们希望的。比如,我们不希望这个Header中的数据成员数目被改动,只要一些预设值!这时上面的灵活性就成了不希 望的结果,因为这个结构中保存数据的个数是可以随时调整的。Python是可以完成这个附加任务的,一个简单的方法是使用python的新型类,也就是继 承于object类的子类。使用新型类的好处是,我们可以添加一个隐含成员__slots__,当这个属性存在时,这个类的『实例』是没有内置字典的!也 就是说,我们不能给这个实例化的对象随意添加成员变量,它所拥有的属性是在类成员__slots__中规定好的,不能添加删除了。但是slots中规定属 性的值还是可以改变的。这样完美实现的我们的要求。
下面看看具体实现:

  1. class Header(object): #新式类
  2. __slots__=['version','var', 'desc']
  3. def __init__(self, **data):
  4. for i, key in enumerate(self.__slots__):
  5. self.__slots__[i] = data[key]

吼,这次好了,可以随意创建一个实例,但是只能用那三个定义好的属性,添加新的是不允许的,这样可以保证我们定义‘结构’的‘安全性’。

就说这些,其实问题是很简单的,你当然可以简单地用一个字典实现,但是还是那句话,不够灵活(添加新成员要呼叫字典的方法才行,或者不能限制成员),但是上面的类可以实现。

阅读(2710) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~