Best way to store fixed-keys key:value datasets that are accessed by keys in python?
我想要的是能够处理具有固定键集的数据集。所有键都是字符串。数据将永远不会被编辑。我知道这可以通过像这样的普通听写来实现:
1 2 3 | data_a = {'key1': 'data1a', 'key2': 'data2a', 'key3': 'data3a'} data_b = {'key1': 'data1b', 'key2': 'data2b', 'key3': 'data3b'} data_c = {'key1': 'data1c', 'key2': 'data2c', 'key3': 'data3c'} |
他们必须能够这样称呼:
1 | data_a['key1'] # Returns 'data1a' |
号
但是,这看起来是浪费内存(因为字典显然会让自己保持1/3的空间或类似的空间,同时还会多次存储键),而且创建起来也很麻烦,因为我需要在代码中反复输入相同的键。我还可能会意外地更改数据集中的某些内容。
我目前的解决方案是先将一组键存储在一个元组中,然后将数据也存储为元组。看起来是这样的:
1 2 3 4 | keys = ('key1', 'key2', 'key3') data_a = ('data1a', 'data2a', 'data3a') data_b = ('data1b', 'data2b', 'data3b') data_c = ('data1b', 'data2c', 'data3c') |
要检索数据,我将执行以下操作:
1 | data_a[keys.index('key1')] # Returns 'data1a' |
。
然后,我了解了这个叫做命名双重的东西,它似乎可以做我需要的事情:
1 2 3 4 5 | import collections Data = collections.namedtuple('Data', ('key1', 'key2', 'key3')) data_a = Data('data1a', 'data2a', 'data3a') data_b = Data('data1b', 'data2b', 'data3b') data_c = Data('data1b', 'data2c', 'data3c') |
但是,似乎我不能简单地通过键调用值。相反,要通过键检索数据,我必须使用getattr,这看起来不太直观:
1 | getattr(data_a,'key1') # Returns 'data1a' |
。
我的标准是内存效率,首先是性能效率。在这三种方法中,哪一种是最好的方法?或者我错过了什么,还有一个更像Python的成语来得到我想要的?
编辑:我最近还了解了
是的,
1 2 3 4 5 6 7 8 9 10 | class Data: __slots__ = ["key1","key2"] def __init__(self, k1, k2): self.key1, self.key2 = k1, k2 def __getitem__(self, key): if key not in self.__slots__: raise KeyError("%r not found" % key) return getattr(self, key) |
。
让我们试试看:
1 2 | >>> Data(1, 2)["key1"] 1 |
以
1 2 3 4 5 6 7 8 9 10 11 | In [1]: %paste import collections Data = collections.namedtuple('Data', ('key1', 'key2', 'key3')) data_a = Data('data1a', 'data2a', 'data3a') data_b = Data('data1b', 'data2b', 'data3b') data_c = Data('data1b', 'data2c', 'data3c') ## -- End pasted text -- In [2]: data_a.key1 Out[2]: 'data1a' |
文档中也演示了这种用法:
1 2 3 4 5 6 7 8 9 10 11 12 | >>> # Basic example >>> Point = namedtuple('Point', ['x', 'y']) >>> p = Point(11, y=22) # instantiate with positional or keyword arguments >>> p[0] + p[1] # indexable like the plain tuple (11, 22) 33 >>> x, y = p # unpack like a regular tuple >>> x, y (11, 22) >>> p.x + p.y # fields also accessible by name 33 >>> p # readable __repr__ with a name=value style Point(x=11, y=22) |
号
如果第二个参数(属性名)是常量,则通常不使用
1 2 3 4 5 | In [3]: attr = input('Attribute: ') Attribute: key3 In [4]: getattr(data_b, attr) Out[4]: 'data3b' |