Pythonで空のリストの辞書を初期化するにはどうすればよいですか?


88

プログラムでリストの辞書を作成しようとしても、辞書キーを個別にアドレス指定できません。リストの辞書を作成して1つのキーに追加しようとすると、すべてのキーが更新されます。非常に単純なテストケースを次に示します。

data = {}
data = data.fromkeys(range(2),[])
data[1].append('hello')
print data

実結果: {0: ['hello'], 1: ['hello']}

期待される結果: {0: [], 1: ['hello']}

これが機能するものです

data = {0:[],1:[]}
data[1].append('hello')
print data

実際の結果と期待される結果: {0: [], 1: ['hello']}

fromkeysメソッドが期待どおりに機能しないのはなぜですか?

回答:


111

[]2番目の引数としてdict.fromkeys()渡すと、かなり役に立たない結果になります。ディクショナリ内のすべての値は同じリストオブジェクトになります。

Python 2.7以降では、代わりに二分法の理解を使用できます。

data = {k: [] for k in range(2)}

以前のバージョンのPythonでは、

data = dict((k, []) for k in range(2))

3
これはかなり直感的でない動作です。すべてのキーに同じオブジェクトが使用される理由について何か考えはありますか?
バー

2
@BarPython言語のセマンティクス内で関数が実行できることは他にないためです。すべてのキーの値として使用される単一のオブジェクトを渡すため、すべてのキーに単一のオブジェクトが使用されます。fromkeys()代わりに、メソッドがファクトリ関数を受け入れる方がよいのでlist、関数として渡すことができ、作成されたキーごとにその関数が1回呼び出されますが、これはの実際のAPIではありませんdict.fromkeys()
Sven Marnach 2016

3
これはまったく直感的ではありません。これを見つけるのに1時間かかりました。おかげで
アストリッド

1
2番目の引数としてdict()を渡した場合も、同じことが起こります。非常に不可解な行動。
オルリー

@Orlyこれは、最初に1つの空のディクショナリが作成され、次にそのディクショナリへの参照がすべての初期化に渡されるためです。
Dr_Zaszuś

83

代わりにdefaultdictを使用してください。

from collections import defaultdict
data = defaultdict(list)
data[1].append('hello')

このように、リストに使用するすべてのキーを事前に初期化する必要はありません。

あなたの例で起こっていることは、1つの(可変の)リストを使用することです:

alist = [1]
data = dict.fromkeys(range(2), alist)
alist.append(2)
print data

出力します{0: [1, 2], 1: [1, 2]}


2
私の場合、残りのプログラムロジックが期待どおりに機能するように、事前にすべてのキーを初期化する必要がありますが、それ以外の場合はこれが適切な解決策になります。ありがとう。
マーティンバーチ2012

この答えに欠けているのは、OPのソリューションとは対照的に、このソリューションが機能するということだと思います。これlistは、空のリストではなく、型であるためです(または、呼び出し可能なコンストラクターとして表示できます)。したがって、欠落しているキーが渡されるたびに、同じリストを再利用する代わりに、新しいリストが作成されます。
Dr_Zaszuś

8

辞書に単一のリストへの参照を入力しているため、辞書を更新すると、更新はすべての参照に反映されます。代わりに辞書の理解を試してください。Pythonでリスト内包表記を使用して辞書を作成するを参照してください。

d = {k : v for k in blah blah blah}

辞書の値を初期化するための素晴らしい提案... cobieに感謝します!例を拡張して、既存の辞書の値をリセットしました。d。私はこれを次のように実行しました:d = {k:0 for k in d}
John

vこの答えには何が含まれていますか?
Dr_Zaszuś

-2

あなたはこれを使うことができます:

data[:1] = ['hello']

2
これが機能する理由を説明することは、OPにとって役立つ場合があります。投稿された元の質問は、なぜそれが期待どおりに機能しないのかを確認します。
william.taylor.09 2017年

@ william.taylor.09なぜこれが機能するのかは明らかですよね?
コナーダッセン2017年

OPは、「fromkeysメソッドが期待どおりに機能しないのはなぜですか?」と質問しています。
william.taylor.09 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.