TypeError: shahableble type: 'dict'


175

Bu kod parçası bana bir hata veriyor unhashable type: dictHerkes çözümün ne olduğunu açıklayabilir

negids = movie_reviews.fileids('neg')
def word_feats(words):
    return dict([(word, True) for word in words])

negfeats = [(word_feats(movie_reviews.words(fileids=[f])), 'neg') for f in negids]
stopset = set(stopwords.words('english'))

def stopword_filtered_word_feats(words):
    return dict([(word, True) for word in words if word not in stopset])

result=stopword_filtered_word_feats(negfeats)


3
Sorunun hangi satırda olduğunu görebilmemiz için hata raporunu göstermek faydalı olacaktır ...
drevicko

Yanıtlar:


249

A'yı dictbaşka bir anahtar için dictveya bir anahtar kelime olarak kullanmaya çalışıyorsunuz set. Bu işe yaramaz çünkü anahtarlar yıkanabilir olmalıdır. Genel bir kural olarak, sadece değiştirilemeyen nesneler (teller, tamsayılar, şamandıralar, frozensets, değişmezler tuples) yıkanabilir (istisnalar mümkündür). Yani bu işe yaramıyor:

>>> dict_key = {"a": "b"}
>>> some_dict[dict_key] = True
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'

Bir dikteyi anahtar olarak kullanmak için, önce karma olabilen bir şeye dönüştürmeniz gerekir. Anahtar olarak kullanmak istediğiniz dikte yalnızca değişmez değerlerden oluşuyorsa, bunun gibi yıkanabilir bir temsili oluşturabilirsiniz:

>>> key = frozenset(dict_key.items())

Artık keya dictveya set:

>>> some_dict[key] = True
>>> some_dict
{frozenset([('a', 'b')]): True}

Elbette, bir diksiyon kullanarak bir şey aramak istediğinizde egzersizi tekrarlamanız gerekir:

>>> some_dict[dict_key]                     # Doesn't work
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>> some_dict[frozenset(dict_key.items())]  # Works
True

Eğer dictanahtar kendilerini dicts ve / veya listeleri değerlere sahip olarak kullanmak istediğiniz, özyinelemeli müstakbel anahtarı "dondurmak" gerekir. İşte bir başlangıç ​​noktası:

def freeze(d):
    if isinstance(d, dict):
        return frozenset((key, freeze(value)) for key, value in d.items())
    elif isinstance(d, list):
        return tuple(freeze(value) for value in d)
    return d

2
Teşekkürler, işe yarıyor, ancak değer bir dict veya liste (shahable) ise hala hata alıyorum, şimdi hash kullanıyorum (str (my_dict)), benim için iyi çalışıyor.
Steven Du

7
@StevenDu sözlükleri siparişi garanti etmez, bu nedenle str(my_dict)aynı (veya farklı, ama eşdeğer) dikler için iki farklı dize döndürebilir
K Raphael

1
Ortaya çıkan frozenset'i dikteye geri dönüştürmek için arayın dict(the_frozenset).
kullanıcı

4
Bana öyle geliyor ki frozenset(dict_key.items()), aynı içeriğe sahip ancak farklı yerleştirme sırasına sahip iki dikte aynı anahtarla sonuçlanmayabilir. Sort () öğesine bir çağrı eklemek sırayla görünüyor. Örneğin frozenset(sorted(dict_key.items())), setlerin açıkça sırasız olduğu göz önüne alındığında, frozenset garip bir seçim gibi görünüyor. Muhtemelen pratikte iyi çalışıyor, ancak tuple benim için daha mantıklı bir seçim gibi görünüyor. tuple(sorted(dict_key.items()))
Birlikte

@JasonHeiss
kullanıcı3732361

6

Olası bir çözüm JSON dumps () yöntemini kullanmak olabilir, böylece sözlüğü bir dizeye dönüştürebilirsiniz ---

import json

a={"a":10, "b":20}
b={"b":20, "a":10}
c = [json.dumps(a), json.dumps(b)]


set(c)
json.dumps(a) in c

Çıktı -

set(['{"a": 10, "b": 20}'])
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.