【Python技巧系列】Python中key-value格式数据存储⽅案
key-value格式的存储的应⽤场景很多,通⽤的描述是『输⼊⼀个唯⼀标识的input,返回(查)⼀个对应的output』。Python中字典(dictionary)就是⼀个内置的解决⽅案 - Python的字典本质上是⼀个哈希表,功能可对应Java的HashMap,但据说被尽可能地优化过(没有研究过细节,不随意展开),因此输⼊key的查询速度可以说是Python本⾝能达到的极致了。但是,并不是每个场景都是以查询速度为第⼀条件的。Python字典在建⽴的过程中同时也要建⽴⼀个C long型的哈希表(以及其他?),因此会额外占据很多空间。若是需要在内存中保持⼀个很⼤的key-value数据结构,并可以牺牲查询速度的话,也可以⽤其他⽅案替代。
这篇整理⼀下Python中各种常⽤的key-value⽅案以及适⽤场景。
优点:⽅便简洁,查询速度No.1
缺点:占⽤内存空间。
适⽤场景:内存⾜够。
这⾥我们主要关⼼的是,Series / DataFrame的索引中,⽤户⾃定义索引和内部建⽴的数值型索引的映射是怎么实现的?(重点 - 是字典吗?答案:是。)
拿Series来举例:
class Series(base.IndexOpsMixin, strings.StringAccessorMixin,
generic.NDFrame,):
def __init__(self, data=None, index=None, dtype=None, name=None,
copy=False, fastpath=False):
...
self._set_axis(0, index, fastpath=True)
def _set_axis(self, axis, labels, fastpath=False):
...
self._data.set_axis(axis, labels)
...
其中._data是generic.NDFrame初始化设置的对象属性值:
class NDFrame(PandasObject):
def __init__(self, data, axes=None, copy=False, dtype=None,
fastpath=False):
...
object.__setattr__(self, '_data', data)
...
因此,我们追溯到.ic.NDFrames中定义的set_axis⽅法:
def set_axis(self, axis, labels):
""" public verson of axis assignment """
setattr(self, self._get_axis_name(axis), labels)
⼜追溯到同类中的_get_axis_name⽅法:
def _get_axis_name(self, axis):
axis = self._(axis, axis)
if isinstance(axis, string_types):
if axis in self._AXIS_NUMBERS:
return axis
else:
try:
return self._AXIS_NAMES[axis]
except:
pass
raise ValueError('No axis named {0} for object type {1}'
.format(axis, type(self)))
其中⽤到的._AXIS_ALIASES,_AXIS_NUMBERS,_AXIS_NAMES⼜追溯到了当前类的_setup_axes⽅法:
@classmethod
def _setup_axes(cls, axes, info_axis=None, stat_axis=None, aliases=None,
slicers=None, axes_are_reversed=False, build_axes=True,
ns=None):
cls._AXIS_ORDERS = axes
cls._AXIS_NUMBERS = dict((a, i) for i, a in enumerate(axes))
cls._AXIS_LEN = len(axes)
cls._AXIS_ALIASES = aliases or dict()
python 定义数组
cls._AXIS_IALIASES = dict((v, k) for k, v in cls._AXIS_ALIASES.items())
cls._AXIS_NAMES = dict(enumerate(axes))
cls._AXIS_SLICEMAP = slicers or None
cls._AXIS_REVERSED = axes_are_reversed
这个函数在series.py这个⽂件中是在class series外使⽤的,也就是⼀import就直接被执⾏,为以上的⼏个属性进⾏赋值(初始化?):
Series._setup_axes(['index'], info_axis=0, stat_axis=0, aliases={'rows': 0})
因此我们可以看到,axes,或者说axis,index的alias别名和实际使⽤⽤来查的内部使⽤的index序号是⽤字典来映射的。也就是说,如果我们仅仅要⽤Series来存储⼀个key-value的数据结构,在存储上是和字典⼀个级别的。
优点:数据分析功能多样。
缺点:同字典。
适⽤场景:内存⾜够,并且需要进⾏数据分析的活动。
优点:可选择在硬盘上存储。
缺点:同⼀时间只能被⼀个连接访问修改,其他连接被加锁。
适⽤场景:⽐较通⽤。不介意密集I/O操作,不介意查询速度。
元组是定长数组,列表是不定长数组。元组在存储空间上⽐列表节省16byte,估计是⼀个指针空位(?)
优点:简洁快速。
缺点:太过简陋。
适⽤场景:key可以被序列化,key可以被⼀个公式映射成唯⼀的index,因此能够直接⽤key得知index。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。