web-dev-qa-db-ja.com

Python defaultdictおよびlambda

他の人のコードで、次の2行を読みました。

x = defaultdict(lambda: 0)
y = defaultdict(lambda: defaultdict(lambda: 0))

Defaultdictの引数はデフォルトファクトリなので、最初の行は、存在しないキーk(v = x [k]のようなステートメントなど)に対してx [k]を呼び出すと、キーと値のペア(k 、0)は、ステートメントx [k] = 0が最初に実行されるかのように、辞書に自動的に追加されます。私は正しいですか?

Yはどうですか?デフォルトファクトリーはデフォルト0でdefaultdictを作成するようです。しかし、それは具体的にどういう意味ですか? Python Shellで試してみましたが、それが何であるかを正確に把握できませんでした。

48
user740006

最初の行は、存在しないキーkx[k]のようなステートメントなど)に対してv=x[k]を呼び出すと、キーと値のペア(k,0)が自動的にステートメントx[k]=0が最初に実行されるかのように、辞書に追加されます。

そのとおり。これはより慣用的に書かれています

x = defaultdict(int)

yの場合、y["ham"]["spam"]を実行すると、yにキー"ham"が挿入されます(存在しない場合)。それに関連付けられた値はdefaultdictになり、"spam"0の値が自動的に挿入されます。

つまり、yは一種の「2層」defaultdictです。 "ham" not in yの場合、y["ham"]["spam"]の評価は

y["ham"] = {}
y["ham"]["spam"] = 0

通常のdictに関して。

45
Fred Foo

最初のものが正しいことは正しいです。 yに関しては、キーがyに存在しない場合、デフォルト0でdefaultdictを作成するため、これをネストされた辞書と考えることができます。次の例を考えてみましょう。

y = defaultdict(lambda: defaultdict(lambda: 0))
print y['k1']['k2']   # 0
print dict(y['k1'])   # {'k2': 0}

Defaultdictなしで同等のネストされた辞書構造を作成するには、y['k1']の内部辞書を作成し、y['k1']['k2']を0に設定する必要があります。見られた:

y = {}
y['k1'] = {}
y['k1']['k2'] = 0

以下の関数は、インタープリターでこれをいじって理解を深めるのに役立ちます。

def to_dict(d):
    if isinstance(d, defaultdict):
        return dict((k, to_dict(v)) for k, v in d.items())
    return d

これにより、ネストされたdefaultdictに相当するdictが返されます。

>>> y = defaultdict(lambda: defaultdict(lambda: 0))
>>> y['a']['b'] = 5
>>> y
defaultdict(<function <lambda> at 0xb7ea93e4>, {'a': defaultdict(<function <lambda> at 0xb7ea9374>, {'b': 5})})
>>> to_dict(y)
{'a': {'b': 5}}
8
Andrew Clark

あなたが正しく説明したように、defaultdictはその引数を引数なしでコンストラクタに呼び出します。これはキーが見つからないときに呼び出されます。

_lambda: 0_はもちろん常にゼロを返しますが、それを行うための推奨されるメソッドはdefaultdict(int)で、同じことを行います。

2番目の部分に関しては、トップレベルの辞書にキーが見つからない場合、著者は新しいdefaultdict(int)またはネストされた辞書を作成したいと考えています。

7
Triptych

すべての答えは十分に良いのですが、私はさらに情報を追加するために答えを与えています:

「defaultdictには呼び出し可能な引数が必要です。その呼び出し可能なオブジェクトの結果は、存在しないキーで辞書にアクセスしようとしたときに辞書が返すデフォルト値です。」

ここに例があります

SAMPLE= {'Age':28, 'Salary':2000}
SAMPLE = defaultdict(lambda:0,SAMPLE)

>>> SAMPLE
defaultdict(<function <lambda> at 0x0000000002BF7C88>, {'Salary': 2000, 'Age': 28})

>>> SAMPLE['Age']----> This will return 28
>>> SAMPLE['Phone']----> This will return 0   # you got 0 as output for a non existing key inside SAMPLE
2
Prashant Pathak

y = defaultdict(lambda:defaultdict(lambda:0))

これを試してみると便利ですy['a']['b'] += 1

1
yongsun