5.4 迭代和容器
迭代是Python的核心概念,也是编写高效易读的Python代码的关键。它也是一种浏览组内对象的常用方式。
5.4.1 组如何存储
在HDF5文件内,组的成员以一种名为“B树”的数据结构索引。本书不是计算机学科的教材,所以我们不会花太多时间解释,但我们有必要对背景知识有一个粗略的了解,特别是当你的组含有上万甚至上百万对象时。
“B树”是一种可以在保存大量对象的同时还能快速存取的数据结构。它的工作模式在一个可排序对象(如数值或字符串)的集合上,建立一种树状“索引”来快速访问成员。
假设你有一个HDF5组里面仅有一个成员,而另一个组有一百万成员,那么打开后者不需要花费前者一百万倍的时间。组内成员以名字索引,所以如果你知道对象的名字,那么HDF5可以通过搜索索引来快速定位对象。创建新成员时也是一样,HDF5不需要将成员“插入”巨表当中的某个位置并重排其余成员的位置。
当然这一切对于用户都是透明的。HDF5文件里每一个组都有一个以字母顺序排序的索引用于追踪其成员。记住这字母顺序是C风格的(或者更明确一点,是ASCII的字母顺序):
HDF5文件还有其他可选的索引,比如,记录对象创建时间的索引,不过h5py没有暴露这些接口。
一般来说:h5py会以字母顺序遍历文件中的对象(尤其是对于小型的组来说),但你不能太过依赖这一行为。因为在幕后,HDF5实际上以本地顺序存取对象,基本上这意味着“尽可能快地进行存取”。我们唯一能确保的是如果你不修改组,那么其组内对象的顺序将保持不变。
5.4.2 字典风格的遍历
为了让组以字典的方式工作,HDF5提供了成员名字来在组内进行遍历。记住它们是一些Unicode字符串:
除此以外还提供了iterkeys(同上例)、itervalues和iteritems方法以你期望的方式工作:
另外还有标准的keys、items和values方法,会提供跟上面三例等效的列表。这时候跟遍历组相关的性能提示就来了:除非你真的想要产生一个具有10000个对象的列表,否则请使用iter *版本的方法。
提示
如果你使用Python 3,你会发现你只有keys、values和items方法。这是对的。和Python 3中的字典一样,Python 3中这三个方法返回的是迭代器而不是列表。
5.4.3 测试存在性
这又是一个时不时会跳出来的一个明显的性能问题,你的代码千万别写成下面这样:
每次执行这个语句时都会创建并丢弃一个包含你所有组内成员的列表。使用Python标准的容器测试,你可以充分利用底层HDF5对象名字的索引,这样会非常快:
更关键的是,你还可以使用路径来跨越多个组,当然,由于HDF5需要检查中间组,这会略微慢一点:
好用极了。记住跟访问组成员一样,POSIX风格访问父目录的“..”是无效的。你甚至得不到一个错误消息,HDF5会查找一个名为“..”的组并认为其不存在:
如果你在操作POSIX风格字符串的时候遇到了这个问题,你可以用posixpath模块来封装你的路径:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论