Python Sözlük Anlama


386

Python'da (anahtarlar için) bir sözlük kavraması oluşturmak mümkün müdür?

Liste kavrayışı olmadan, aşağıdaki gibi bir şey kullanabilirsiniz:

l = []
for n in range(1, 11):
    l.append(n)

Bir liste anlayışı bu kısaltabilirsiniz: l = [n for n in range(1, 11)].

Ancak, bir sözlüğün anahtarlarını aynı değere ayarlamak istiyorum diyelim. Yapabilirim:

d = {}
for n in range(1, 11):
     d[n] = True # same value for each

Bunu denedim:

d = {}
d[i for i in range(1, 11)] = True

Ancak, bir olsun SyntaxErrorüzerinde for.

Buna ek olarak (Bu bölüme ihtiyacım yok, ama merak ediyorum), bir sözlüğün anahtarlarını farklı değerler gibi bir grupa ayarlayabilirsiniz:

d = {}
for n in range(1, 11):
    d[n] = n

Bu bir sözlük kavrayışı ile mümkün mü?

d = {}
d[i for i in range(1, 11)] = [x for x in range(1, 11)]

Bu aynı zamanda bir yükseltir SyntaxErrorüzerinde for.


3
Gelecekteki okuyucuların bilgileri için: NumPy dizileri, yapmaya çalıştığınız şekilde birden çok öğeyi tek bir değere veya değer listesine ayarlamanıza izin verir. NumPy'yi kullanmak için bir nedeniniz olmasa da, muhtemelen sadece bu özellik için buna değmez.
David Z

Yanıtlar:


520

Python 2.7 ve daha sonraki sürümlerinde sözlük kavrayışları vardır , ancak sizin denediğiniz şekilde çalışmazlar. Liste kavraması gibi, yeni bir sözlük oluştururlar; mevcut bir sözlüğe anahtar eklemek için bunları kullanamazsınız. Ayrıca, anahtarları ve değerleri belirtmeniz gerekir, ancak isterseniz kukla bir değer belirtebilirsiniz.

>>> d = {n: n**2 for n in range(5)}
>>> print d
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Hepsini True olarak ayarlamak istiyorsanız:

>>> d = {n: True for n in range(5)}
>>> print d
{0: True, 1: True, 2: True, 3: True, 4: True}

Sorduğunuz şey, mevcut bir sözlükte aynı anda birden fazla anahtar ayarlamanın bir yoludur. Bunun için doğrudan bir kısayol yok. Daha önce gösterdiğiniz gibi döngü yapabilir veya yeni değerlerle yeni bir diksiyon oluşturmak için bir sözlük kavrama kullanabilir ve ardından oldDict.update(newDict)yeni değerleri eski dikte birleştirmek için kullanabilirsiniz.


15
FWIW, dict.updateayrıca tıpkı anahtar-değer çiftlerinin bir iterable kabul edebilir dictyapıcı
mgilson

6
Eğer tüm değerler aynı, kullanım bir sözlük oluşturmak için eğer dikkat edin dict.fromkeys(). Tüm değerleri ayarlamak için Truekullanın dict.fromkeys(range(5), True). Dikkat edin, değer kopyalanmaz , bu nedenle değiştirilebilir bir değeriniz olduğunda bundan kaçınmak isteyebilirsiniz; tüm anahtarlar arasında paylaşılacaktır.
Martijn Pieters

2
Not: tuşları yanı bir yöntemin kaynaklanabilir: { n*2 : n for n in range(3) } => {0: 0, 2: 1, 4: 2}. Her ikisi de aynı ifadede yapılabilir: { n*2 : n*3 for n in range(3) } => { 0: 0, 2: 3, 4: 6 }.
Zaaier

151

dict.fromkeysSınıf yöntemini kullanabilirsiniz ...

>>> dict.fromkeys(range(5), True)
{0: True, 1: True, 2: True, 3: True, 4: True}

Bu, tüm anahtarların aynı değerle eşleştiği bir sözlük oluşturmanın en hızlı yoludur.

Ama yok değil değişken nesnelerle bu kullanmak :

d = dict.fromkeys(range(5), [])
# {0: [], 1: [], 2: [], 3: [], 4: []}
d[1].append(2)
# {0: [2], 1: [2], 2: [2], 3: [2], 4: [2]} !!!

Tüm anahtarları gerçekten başlatmanız gerekmiyorsa , a defaultdictda yararlı olabilir:

from collections import defaultdict
d = defaultdict(True)

İkinci kısmı cevaplamak için, bir diksiyon kavraması tam da ihtiyacınız olan şeydir:

{k: k for k in range(10)}

Muhtemelen bunu yapmamalısınız, ancak geçersiz kılma durumunda dictbir şekilde çalışan bir alt sınıf da oluşturabilirsiniz :defaultdict__missing__

>>> class KeyDict(dict):
...    def __missing__(self, key):
...       #self[key] = key  # Maybe add this also?
...       return key
... 
>>> d = KeyDict()
>>> d[1]
1
>>> d[2]
2
>>> d[3]
3
>>> print(d)
{}

Unutmayın ki d = defaultdict(lambda: True) , lamda TRUE olarak gerekli değildir (veya olmamalıdır) kesilebilir olması.
rhbvkleef

28
>>> {i:i for i in range(1, 11)}
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10}

22

Mgilson yorumunu gerçekten seviyorum, çünkü biri yinelenen, biri anahtarlara ve diğeri değerlere karşılık gelen iki tane varsa, aşağıdakileri de yapabilirsiniz.

keys = ['a', 'b', 'c']
values = [1, 2, 3]
d = dict(zip(keys, values))

vererek

d = {'a': 1, 'b': 2, 'c': 3}


4
{i:j for i in keys for j in values}
Diksiyon

11

Bir tuples listesinde dict () kullanın, bu çözüm, aynı uzunlukta olmaları koşuluyla, her listede rastgele değerlere sahip olmanızı sağlar.

i_s = range(1, 11)
x_s = range(1, 11)
# x_s = range(11, 1, -1) # Also works
d = dict([(i_s[index], x_s[index], ) for index in range(len(i_s))])

12
Bir yan not olarak, bu aynı şeyd = dict(zip(i_s,x_s))
mgilson

10

Sözlük anlamayı kullanarak bir listedeki kelimelerin oluşumunu saymanın bu örneğini düşünün

my_list = ['hello', 'hi', 'hello', 'today', 'morning', 'again', 'hello']
my_dict = {k:my_list.count(k) for k in my_list}
print(my_dict)

Ve sonuç

{'again': 1, 'hi': 1, 'hello': 3, 'today': 1, 'morning': 1}

Bu, ilginçtir, ancak en verimli olmasa da, birden çok kez 'merhaba' gibi anahtarları
sayacaksınız

7

Bir liste kavramasının temel amacı, orijinal listeyi değiştirmeden veya yok etmeden başka bir listeye dayalı yeni bir liste oluşturmaktır.

Yazmak yerine

    l = []
    for n in range(1, 11):
        l.append(n)

veya

    l = [n for n in range(1, 11)]

sadece yazmalısın

    l = range(1, 11)

En iyi iki kod bloğunda, listeyi yineleyerek ve her öğeyi döndürerek yeni bir liste oluşturuyorsunuz. Liste kopyası oluşturmanın sadece pahalı bir yolu.

Tüm anahtarlar başka bir dikteye göre aynı değere ayarlanmış yeni bir sözlük almak için şunu yapın:

    old_dict = {'a': 1, 'c': 3, 'b': 2}
    new_dict = { key:'your value here' for key in old_dict.keys()}

Bir SyntaxError alıyorsunuz çünkü yazarken

    d = {}
    d[i for i in range(1, 11)] = True

temel olarak şunu söylüyorsunuz: "Anahtar (i, 1, 11) için i anahtarımı" Doğru "olarak ayarlayın ve" aralık (1, 11) için i için i "geçerli bir anahtar değil, sadece bir sözdizimi hatası. Desteklenen listeleri anahtar olarak belirtirseniz, aşağıdaki gibi bir şey yaparsınız:

    d[[i for i in range(1, 11)]] = True

ve yok

    d[i for i in range(1, 11)] = True

ancak listeler yıkanamaz, bu nedenle bunları dikteli anahtar olarak kullanamazsınız.


-3

böyle bir liste oluşturamazsınız. bunun yerine deneyin, tuples kullanır

d[tuple([i for i in range(1,11)])] = True
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.