Python: defaultdict'i dikte'ye dönüştürme


93

Bir defaultdict'i nasıl dönüştürebilirim

number_to_letter
defaultdict(<class 'list'>, {'2': ['a'], '3': ['b'], '1': ['b', 'a']})

ortak bir diktedir?

{'2': ['a'], '3': ['b'], '1': ['b', 'a']}

11
dict(number_to_letter)
Tim Peters

2
@TimPeters, bu aslında güzel yazılmış bir soru olduğundan, açık bir başlığa sahip (ve aramalarda kolayca görünmelidir), ileride başvurmak için, daha iyi bir dupe bulamazsak, bunu bir cevap olarak koymaya değer. .
Jon Clements

Bu cevap yardımcı olmalı: stackoverflow.com/a/3031915/1628832
karthikr

1
@JonClements, iyi bir nokta, ama DSM çoktan kabul etti - Umarım cevabı kabul edilmiştir :-)
Tim Peters

2
@TimPeters 10.000 btw için tebrikler ... Seni uzun sürmeyeceğini hissettim - bir noktada chat.stackoverflow.com/rooms/6/python ile (utanmaz fiş) patlamalısın :)
Jon Clements

Yanıtlar:


124

Sadece arayabilirsin dict:

>>> a
defaultdict(<type 'list'>, {'1': ['b', 'a'], '3': ['b'], '2': ['a']})
>>> dict(a)
{'1': ['b', 'a'], '3': ['b'], '2': ['a']}

ancak bir varsayılan diktenin bir dikt olduğunu unutmayın :

>>> isinstance(a, dict)
True

sadece biraz farklı bir davranışla, eksik olan bir anahtara erişmeye çalıştığınızda - ki bu normalde a'yı yükseltir KeyError- default_factoryonun yerine çağrılır:

>>> a.default_factory
<type 'list'>

print aSözlüğün veri tarafı görünmeden önce gördüğünüz şey budur .

Dolayısıyla, aslında yeni bir nesne oluşturmadan daha dikte benzeri davranışı geri almanın bir başka yolu, sıfırlamaktır default_factory:

>>> a.default_factory = None
>>> a[4].append(10)
Traceback (most recent call last):
  File "<ipython-input-6-0721ca19bee1>", line 1, in <module>
    a[4].append(10)
KeyError: 4

ama çoğu zaman bu zahmete değmez.


Python ile programlamayı öğrenmeye yeni başlıyorum. Nasıl kullanılacağını biraz daha açıklayabilir misin default_factory? Neler olduğu hakkında hiçbir fikrim yok. Afedersiniz.
user2988464

Ve 'KeyError' nedir?
user2988464

5
@ user2988464: zaten kullandınız default_factory- bu defaultdict, defaultdict(int)veya gibi, ilk etapta yaptığınızda geçtiğiniz işlevdir defaultdict(list). Her zaman sözlükte bir anahtar aramaya çalıştığınızda a['3'], örneğin normal bir sözlükte ya değeri alırsınız ya da bir KeyErroristisna yaratır (bir hata gibi, o anahtarı bulamadığını söyler). Ancak defaultdicta'da, sizin için yeni bir varsayılan değer (bu "varsayılan" değerdir) yapmak için default_factoryişlevi çağırır . defaultdict
DSM

3
Django'nun .items şablon özelliğinin defaultdict ile çalışmayacağına dikkat etmek faydalıdır, bu yüzden buraya geldim! Yani dönüşüm için iyi bir neden var
Ben

2
Ayrıca yararlı not etmek o pickleolamaz kolu (bir dosyaya piton objelerin kaydedileceği) defaultdicts birçok durumda .
drevicko

28

Varsayılan diktiniz yinelemeli olarak tanımlandıysa, örneğin:

from collections import defaultdict
recurddict = lambda: defaultdict(recurddict)
data = recurddict()
data["hello"] = "world"
data["good"]["day"] = True

defaultdict'i tekrar dikteye dönüştürmenin bir başka basit yolu, jsonmodülü kullanmaktır

import json
data = json.loads(json.dumps(data))

ve tabii ki, varsayılan yetkinizde bulunan değerlerin json tarafından desteklenen veri türleriyle sınırlandırılması gerekir, ancak sınıfları veya işlevleri diktede saklamayı düşünmüyorsanız sorun olmamalıdır.


9
İyi fikir, çok kötü, verilerim
JSON'da

15

Hatta bir özyinelemeli dönüştürmek için bir özyinelemeli sürümünü isterseniz defaultdictbir karşı dictaşağıdakileri deneyebilirsiniz:

#! /usr/bin/env python3

from collections import defaultdict

def ddict():
    return defaultdict(ddict)

def ddict2dict(d):
    for k, v in d.items():
        if isinstance(v, dict):
            d[k] = ddict2dict(v)
    return dict(d)

myddict = ddict()

myddict["a"]["b"]["c"] = "value"

print(myddict)

mydict = ddict2dict(myddict)

print(mydict)

İşte ihtiyacım olan şey bu! Maalesef, defaultdict özel bir kodlayıcı olmadan JSON serileştirilemeyen bazı anahtarlara sahip (anahtarlar tuple - benim seçimim değil, sadece benim sorunum)
Kasapo

1
İyi bir. Bir sözlük anlama kullanmak, yalnızca iki katman derinliğinde ise kısadır (yani defaultdict(lambda: defaultdict(int))): {k: dict(v) for k, v in foo.items()}
ggorlen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.