TypeError: अस्वास्थ्यकर प्रकार: 'तानाशाह'


175

कोड का यह टुकड़ा मुझे एक त्रुटि दे रहा unhashable type: dictहै क्या कोई मुझे बता सकता है कि इसका समाधान क्या है

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
यह त्रुटि रिपोर्ट दिखाने के लिए उपयोगी होगा ताकि हम देख सकें कि किस लाइन में समस्या है ...
drevicko

जवाबों:


248

आप dictएक कुंजी के रूप में दूसरे dictया में उपयोग करने का प्रयास कर रहे हैं set। यह काम नहीं करता है क्योंकि चाबियों को धोने योग्य होना चाहिए। एक सामान्य नियम के रूप में, केवल अपरिवर्तनीय वस्तुएँ (तार, पूर्णांक, फ़्लोट्स, फ्रोज़ेन्सेट्स, टुपल्स ऑफ़ इम्यूटेबल्स) हीबल होते हैं (हालाँकि अपवाद संभव हैं)। तो यह काम नहीं करता है:

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

एक मेजर को एक कुंजी के रूप में उपयोग करने के लिए आपको इसे कुछ चीज़ों में बदलना होगा जो पहले होश में हो सकती है। यदि आप जिस कुंजी को कुंजी के रूप में उपयोग करना चाहते हैं, उसमें केवल अपरिवर्तनीय मूल्य शामिल हैं, तो आप इसे इस तरह से एक हैशेबल प्रतिनिधित्व बना सकते हैं:

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

अब आप keyएक dictया में एक कुंजी के रूप में उपयोग कर सकते हैं set:

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

जब भी आप एक तानाशाह का उपयोग करके कुछ देखना चाहते हैं, तो बेशक आपको व्यायाम दोहराने की आवश्यकता है:

>>> 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

यदि dictआप कुंजी के रूप में उपयोग करना चाहते हैं, तो वे मान हैं जो स्वयं dicts और / या सूचियाँ हैं, आपको भावी कुंजी को पुन: "फ्रीज" करने की आवश्यकता है। यहाँ एक प्रारंभिक बिंदु है:

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
धन्यवाद, यह काम करता है, हालांकि अभी भी त्रुटि मिलती है यदि मूल्य एक तानाशाह या सूची (उपलब्ध नहीं) है, अब मैं हैश (str (my_dict)) का उपयोग कर रहा हूं, मेरे लिए ठीक काम करता है।
स्टीवन ड्यू

7
सिर्फ एक नोट @StevenDu शब्दकोशों आदेश की गारंटी नहीं देता है, इसलिए str(my_dict)एक ही (या अलग, लेकिन समकक्ष) के लिए दो अलग-अलग तार वापस कर सकते हैं
के राफेल

1
परिणामी फ्रोजेनसेट को वापस से परिवर्तित करने के लिए, बस कॉल करें dict(the_frozenset)
उपयोगकर्ता

4
यह मुझे लगता है कि frozenset(dict_key.items())एक ही सामग्री के साथ उस दो dicts में संभावित रूप से समस्याग्रस्त है, लेकिन अलग-अलग सम्मिलन क्रम में एक ही कुंजी का परिणाम नहीं हो सकता है। क्रमबद्ध करने के लिए कॉल जोड़ना () क्रम में लगता है। उदाहरण के लिए frozenset(sorted(dict_key.items())), फ्रोज़ेन्सेट एक अजीब विकल्प की तरह लगता है जो सेट स्पष्ट रूप से अनियंत्रित है। यह शायद अभ्यास में ठीक काम करता है, लेकिन टपल मुझे अधिक तार्किक पसंद लगता है। मैं साथ चला गयाtuple(sorted(dict_key.items()))
जेसन Heiss

@JasonHeiss से सहमत
user3732361

6

JSON डंप () विधि का उपयोग करने के लिए एक संभावित समाधान हो सकता है, इसलिए आप शब्दकोश को स्ट्रिंग में बदल सकते हैं ---

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

आउटपुट -

set(['{"a": 10, "b": 20}'])
True

2
यह होना चाहिए dumps, नहीं dump
कुषाण गुनासेकरा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.