Neden dict.get (anahtar) işe yaradı ama [anahtar] 'ı dikte etmedi?


17

Ben dize kaç tane var 1 dayalı belirli sayıların ikili dizeleri birlikte gruplandırmaya çalışıyorum.

Bu işe yaramaz:

s = "0 1 3 7 8 9 11 15"
numbers = map(int, s.split())
binaries = [bin(x)[2:].rjust(4, '0') for x in numbers]

one_groups = dict.fromkeys(range(5), [])
for x in binaries:
    one_groups[x.count('1')] += [x]

Beklenen Sözlük one_groupsihtiyaçlar olmak

{0: ['0000'], 
 1: ['0001', '1000'], 
 2: ['0011', '1001'], 
 3: ['0111', '1011'], 
 4: ['1111']}

Ama anladım

{0: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 1: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 2: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 3: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 4: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111']}

Şimdiye kadar işe yarayan tek şey kullanmak one_groups[x.count('1')] = one_groups.get(x.count('1')) + [x]yerineone_groups[x.count('1')] += [x]

Ama neden böyle? Doğru hatırlıyorsam, dict[key]nasıl dict.get(key)çalıştığına benzer şekilde, sözlüğün değerini döndürmem gerekiyor mu? Bu konuyu gördüm Neden dict [key] yerine dict.get (anahtar)? ama bu özel durum için soruma cevap vermedi, çünkü programınKeyError

Ben de denedim one_groups[x.count('1')].append(x)ama bu da çalışmıyor.


8
getNoneanahtar yoksa veya sağlanan herhangi bir varsayılan değer döndürülürken , dizin operatörü []anahtar yoksa bir hata oluşturur.
adnanmuttaleb

Sidenote, bin(x)[2:].rjust(4, '0')basitleştirilebilir '{:0>4b}'.format(x).
wjandrea

1
BTW, minimal tekrarlanabilir bir örnek oluşturmaya yardımcı olur . Bu durumda nasıl yaptığınız binariessoru ile ilgili değildir, bu yüzden sadece değerini sağlayabilirsiniz.
wjandrea

Yanıtlar:


24

Sorun değişebilirliktir:

one_groups = dict.fromkeys(range(5), [])- bu , tüm anahtarlara değerle aynı listeyi iletir . Yani bir değeri değiştirirseniz, hepsini değiştirirsiniz.

Temel olarak şunu söylemekle aynı şeydir:

tmp = []
one_groups = dict.fromkeys(range(5), tmp)
del tmp

Yeni bir liste kullanmak istiyorsanız, listeyi bir döngüde yapmanız gerekir - açık bir fordöngü veya bir diksiyon kavramada:

one_groups = {key: [] for key in range(5)}

Bu şey her anahtar için "yürütür" [](buna eşittir list()), böylece değerleri farklı listelerle yapar.


Neden getçalışıyor? Çünkü geçerli listeyi açıkça alırsınız, ancak +yeni bir sonuç listesi yaparsınız . Ve o olsun önemli değil one_groups[x.count('1')] = one_groups.get(x.count('1')) + [x]ya one_groups[x.count('1')] = one_groups[x.count('1')] + [x]- önemli olan orada olmasıdır+ .

Herkesin diyor biliyorum a+=badildir a=a+blistelerde durumunda, - fakat uygulama optimizasyonu için farklı olabilir +=adildir .extendböylece hafıza kaybı olacaktır yeni bir liste oluşturarak, mevcut değişken bizim sonucunu istediğini biliyorum çünkü.


Ah, evet, anladım. Ben de kullanarak bir 2D liste oluşturmak istediğimde mylist = [[] * 5] * 5ve nasıl düzeltebileceğime benzer bir sorun yaşadığımı hatırlıyorum mylist = [[] for x in range(5)] * 5. Sadece hızlı bir açıklama için, anladığım kadarıyla, bu boş listenin bellek adresini gösteren değişkenler nedeniyle olur. Bu aynı zamanda ilkelleri kullansam sorunun oluşmayacağı anlamına mı geliyor?
SpectraXCD

1
Evet, ilkelleri kullandıysanız bu sorunu çözecektir, ancak kırılacaktır one_groups[x.count('1')] += [x]çünkü ilkel bir türe liste ekleyemezsiniz. Bunun yerine daha iyi bir çözüm defaultdict kullanmaktır.
Fakher Mokadem

4
özel olarak ise, +aramaları __add__, yeni bir obje ve döner iken +=aramalar__iadd__ ve yeni bir nesneyi döndürmek için gerekli değildir
njzk2

8

Sorun kullanıyor one_groups = dict.fromkeys(range(5), [])

(Bu, tüm anahtarlara değerle aynı listeyi iletir. Dolayısıyla, bir değeri değiştirirseniz, hepsini değiştirirsiniz)


Bunun yerine şunları kullanabilirsiniz: one_groups = {i:[] for i in range(5)}

(Bu şey her anahtar için "yürütür" [] (listeye () eşittir), böylece değerleri farklı listelerle yapar.)


6
Bir açıklama gerçekten yararlı olsa da, kesinlikle haklısın. İki çizgi arasındaki farkın ne olduğu gerçekten çok önemli değil.
Simon Fink

Evet, benim hatam. üzgünüm
Hameda169

4

DICT'in fromkeysyöntemindeki yardım budur .

Yerleşik işlev konusunda tuşlardan yardım:

builtins.type örneği fromkeys (iterable, value = None, /) yöntemi yinelenebilir anahtarları ve değerleri değere ayarlanmış yeni bir sözlük oluşturma

Bu, fromkeys bir değeri kabul edeceğini ve hatta çağrılabilir olsa bile, önce onu değerlendirecek ve daha sonra bu değeri tüm dikt tuşlarına atayacağını söylüyor.

Listeler Python'da değiştirilebilir ve bu nedenle aynı boş liste referansını atar ve bir değişiklik hepsini etkiler.

Bunun yerine defaultdict komutunu kullanın:

>>> from collections import defaultdict
>>> one_groups = defaultdict(list)
>>> for x in binaries:
      one_groups[x.count('1')] += [x]
>>> one_groups = dict(one_groups) # to stop default dict behavior

Bu, mevcut olmayan anahtarlara atamaları kabul eder ve değerler boş listelere varsayılan olarak (bu durumda).

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.