2

私が欲しいのは、キーの固定セットを持つデータのセットを処理できるようにすることです。すべてのキーは文字列です。データは編集されません。これは、次のような通常の辞書で実行できることを知っています。

data_a = {'key1': 'data1a', 'key2': 'data2a', 'key3': 'data3a'}
data_b = {'key1': 'data1b', 'key2': 'data2b', 'key3': 'data3b'}
data_c = {'key1': 'data1c', 'key2': 'data2c', 'key3': 'data3c'}

次のように呼び出せる必要があります。

data_a['key1'] # Returns 'data1a'

ただし、これはメモリの浪費のようです (辞書はキーを複数回保存するだけでなく、明らかに 1/3 を空のままにしておくため)、同じキーを入力し続ける必要があるため、作成するのも面倒です。私のコードで何度も何度も。また、データセット内の何かを誤って変更する危険もあります。

私の現在の解決策は、最初にキーのセットをタプルに格納してから、データもタプルとして格納することです。次のようになります。

keys = ('key1', 'key2', 'key3')
data_a = ('data1a', 'data2a', 'data3a')
data_b = ('data1b', 'data2b', 'data3b')
data_c = ('data1b', 'data2c', 'data3c')

データを取得するには、次のようにします。

data_a[keys.index('key1')] # Returns 'data1a'

次に、namedtuples と呼ばれる、必要なことを実行できるように見えるこのことについて学びました。

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 を使用する必要がありますが、これはあまり直感的ではないようです。

getattr(data_a,'key1') # Returns 'data1a'

私の基準は、まずメモリ効率、次にパフォーマンス効率です。これらの 3 つの方法のうち、どの方法が最適でしょうか? それとも、何かが足りないので、欲しいものを手に入れるためのよりPython的なイディオムがありますか?

EDIT:最近、の存在についても学びました。これは__slots__、キーと値のペアに対してより効率的に実行され、同じ(?)量のメモリをほとんど消費しているようです。これと同様に動作する実装は、namedtuples の適切な代替になるでしょうか?

4

2 に答える 2

1

はい、__slots__する必要があります。

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)

それを試してみましょう:

>>> Data(1, 2)["key1"]
1

条件key not in self.__slots__は健全性チェックです。それが存在しなかった場合、私たちのためにgetattr喜んでフェッチします。__init__

于 2013-01-13T10:34:43.397 に答える
1

namedtuple使用するのが正しいようです。getattr「キー」が固定されている場合は、オブジェクトの属性を取得するために通常の構文を使用する必要はなく、使用できます。

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'

この使用法は、ドキュメントにも示されています。

>>> # 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)

getattr通常、2番目の引数(属性名)が定数の場合は使用しません。変更される可能性がある場合にのみ必要です。

In [3]: attr = input('Attribute: ')
Attribute: key3

In [4]: getattr(data_b, attr)
Out[4]: 'data3b'
于 2013-01-13T07:29:54.150 に答える