Python'da boş listelerden oluşan bir sözlüğü nasıl başlatırım?


89

Programlı olarak bir liste sözlüğü oluşturma girişimim, sözlük anahtarlarını tek tek ele almama izin vermiyor. Listelerin sözlüğünü her oluşturduğumda ve bir tuşa eklemeye çalıştığımda, hepsi güncelleniyor. İşte çok basit bir test durumu:

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

Gerçek sonuç: {0: ['hello'], 1: ['hello']}

Beklenen Sonuç: {0: [], 1: ['hello']}

İşte işe yarayan şey

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

Gerçek ve Beklenen Sonuç: {0: [], 1: ['hello']}

fromkeysYöntem neden beklendiği gibi çalışmıyor?

Yanıtlar:


112

[]İkinci argüman olarak geçmek dict.fromkeys()oldukça gereksiz bir sonuç verir - sözlükteki tüm değerler aynı liste nesnesi olacaktır.

Python 2.7 veya üstünde, bunun yerine sözlüksel bir anlama kullanabilirsiniz:

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

Python'un önceki sürümlerinde şunları kullanabilirsiniz:

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

3
Peki bu oldukça mantıksız bir davranış, tüm anahtarlar için aynı nesnenin neden kullanıldığına dair bir fikriniz var mı?
Bar

3
@Bar Çünkü işlevin Python dilinin anlambiliminde yapabileceği başka bir şey yoktur. Tüm anahtarlar için değer olarak kullanılacak tek bir nesne iletirsiniz, böylece tüm anahtarlar için tek bir nesne kullanılır. fromkeys()Yöntemin bunun yerine bir fabrika işlevini kabul etmesi daha iyi olurdu , böylece listbir işlev olarak geçebiliriz ve bu işlev, oluşturulan her anahtar için bir kez çağrılırdı, ancak bu dict.fromkeys(),.
Sven Marnach

3
Bu hiç de sezgisel değil. Bunu bulmam bir saat sürdü. Teşekkürler
Astrid

1
İkinci argüman olarak dict () 'yi geçerseniz de aynı şey olur. Çok şaşırtıcı bir davranış.
Orly

@Orly Bunun nedeni, ilk olarak boş bir sözlüğün oluşturulması ve ardından tüm başlatmalara bir referansın iletilmesidir.
Dr_Zaszuś

83

Kullanım defaultdict yerine:

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

Bu şekilde, kullanmak istediğiniz tüm anahtarları önceden listelemek zorunda kalmazsınız.

Örneğinizde olan şey, bir (değiştirilebilir) liste kullanmanızdır:

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

çıktı {0: [1, 2], 1: [1, 2]}.


2
Benim durumumda, program mantığının geri kalanı beklendiği gibi çalışabilmesi için tüm anahtarları önceden başlatmam gerekiyor, ancak aksi takdirde bu iyi bir çözüm olurdu. Teşekkürler.
Martin Burch

Sanırım bu cevapta eksik olan şey, bu çözümün OP'nin aksine çalıştığını söylemektir, çünkü listburada boş bir liste değil, bir tür (ya da çağrılabilir bir kurucu olarak görebilirsiniz, sanırım). Böylece her eksik anahtar geçildiğinde, aynı olanı yeniden kullanmak yerine yeni bir liste oluşturulur.
Dr_Zaszuś

8

Sözlüklerinizi tek bir listeye referanslarla dolduruyorsunuz, böylece onu güncellediğinizde, güncelleme tüm referanslara yansıtılır. Bunun yerine bir sözlük anlamayı dene. Python'da liste kavrama özelliğine sahip bir sözlük oluşturma konusuna bakın

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

sözlük değerlerini başlatmak için harika bir öneri ... teşekkürler cobie! Mevcut bir sözlükteki değerleri sıfırlamak için örneğinizi genişlettim, d. Bunu şu şekilde yaptım: d = {k: 0 for k in d}
John

vBu cevapta ne var ?
Dr_Zaszuś

-3

Bunu kullanabilirsin:

data[:1] = ['hello']

2
Bunun neden işe yaradığını açıklamak OP'ye yardımcı olabilir . Asıl soru neden beklendiği gibi çalışmadığını sordu.
william.taylor.09

@ william.taylor.09 bunun neden işe yaradığı belli değil mi?
Conner Dassen

OP, "fromkeys yöntemi beklendiği gibi çalışmıyor?"
william.taylor.09
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.