ここで、尋ねられた質問に答えます
なぜPythonはそのままでは提供しないのですか?
私はそれがZen of Pythonに関係しているのではないかと疑っています。これは、辞書からのアクセス値には2つの明確な方法を作成します。obj['key']
とobj.key
。
警告と落とし穴
これらには、コードの明確性の欠如と混乱の可能性が含まれます。つまり、次のコードは、後日コードを保守する他のユーザーを混乱させる可能性があります。しばらくの間コードに戻らないと、混乱を招く可能性があります。繰り返しますが、Zenから:「読みやすさが重要です!」
>>> KEY = 'spam'
>>> d[KEY] = 1
>>> # Several lines of miscellaneous code here...
... assert d.spam == 1
場合はd
、インスタンス化されるか、 KEY
定義されているか、 d[KEY]
遠く離れた場所から割り当てられているd.spam
使用されている、これは一般的に使用されるイディオムではないので、それは簡単に、行われているものについての混乱につながることができます。私が混乱する可能性があることは知っています。
さらに、の値をKEY
次のように変更した場合(ただし、を変更しd.spam
ない場合)、次のようになります。
>>> KEY = 'foo'
>>> d[KEY] = 1
>>> # Several lines of miscellaneous code here...
... assert d.spam == 1
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AttributeError: 'C' object has no attribute 'spam'
IMO、努力する価値はありません。
他の項目
他の人が述べたように、(文字列だけでなく)ハッシュ可能なオブジェクトをdictキーとして使用できます。例えば、
>>> d = {(2, 3): True,}
>>> assert d[(2, 3)] is True
>>>
合法ですが
>>> C = type('C', (object,), {(2, 3): True})
>>> d = C()
>>> assert d.(2, 3) is True
File "<stdin>", line 1
d.(2, 3)
^
SyntaxError: invalid syntax
>>> getattr(d, (2, 3))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: getattr(): attribute name must be string
>>>
ではありません。これにより、オブジェクト属性にアクセスする場合にはない、辞書キーの印刷可能な文字またはその他のハッシュ可能なオブジェクトの全範囲にアクセスできます。これにより、Pythonクックブック(Ch。9)のレシピのような、キャッシュされたオブジェクトのメタクラスのような魔法が可能になります。
ここで私は編集します
私はの美学を好むspam.eggs
以上spam['eggs']
(私はそれがきれいに見えると思いますが)、と私は本当に私が会ったときに、この機能を渇望始めましたnamedtuple
。しかし、次のことができるという利便性はそれよりも優先されます。
>>> KEYS = 'spam eggs ham'
>>> VALS = [1, 2, 3]
>>> d = {k: v for k, v in zip(KEYS.split(' '), VALS)}
>>> assert d == {'spam': 1, 'eggs': 2, 'ham': 3}
>>>
これは簡単な例ですが、obj.key
記法を使用する場合とは異なる状況(つまり、XMLファイルから設定を読み込む必要がある場合)でディクテーションを使用することがよくあります。他のケースでは、動的なクラスをインスタンス化して、美的な理由でいくつかの属性を平手打ちにしたい場合、読みやすさを向上させるために一貫性のためにdictを使い続けます。
OPが長い間これを満足に解決したと確信していますが、それでもこの機能が必要な場合は、それを提供するパッケージのいずれかをpypiからダウンロードすることをお勧めします。
束は私がより身近なものです。のサブクラスなdict
ので、そのすべての機能を利用できます。
AttrDictもかなり良いように見えますが、私はそれに慣れていないため、 Bunchほど詳細にソースを調べていません。
- Addictは積極的に維持され、attrのようなアクセスなどを提供します。
- ロタレティのコメントで述べたように、バンチは廃止されましたが、マンチと呼ばれるアクティブなフォークがあります。
ただし、彼のコードを読みやすくするために、彼の表記スタイルを混在させないことを強くお勧めします。この表記法を使用する場合は、動的オブジェクトをインスタンス化し、必要な属性を追加して、1日で呼び出す必要があります。
>>> C = type('C', (object,), {})
>>> d = C()
>>> d.spam = 1
>>> d.eggs = 2
>>> d.ham = 3
>>> assert d.__dict__ == {'spam': 1, 'eggs': 2, 'ham': 3}
コメントのフォローアップ質問に回答するために更新します
Elmoはコメント(下記)で次のように尋ねています。
あなたがさらに深く行きたいならどうしますか?(type(...)を参照)
このユースケースを使用したことはありませんが(ここでも、dict
一貫性を保つためにを使用する傾向があります)、次のコードが機能します。
>>> C = type('C', (object,), {})
>>> d = C()
>>> for x in 'spam eggs ham'.split():
... setattr(d, x, C())
... i = 1
... for y in 'one two three'.split():
... setattr(getattr(d, x), y, i)
... i += 1
...
>>> assert d.spam.__dict__ == {'one': 1, 'two': 2, 'three': 3}
collections.namedtuple
これには非常に便利です。