3

I'm trying to script a simple Character Generator that I can use for Pen and Paper RPG's. I was thinking about storing all my information in a nested dictionary and saving it into a JSON file.

However, while creating the following dictionary, I receive as error:

nhashable type: 'dict', focussing on {'cha': 1}}}

core_phb = {
'races': {
    'Human': {
        {'abilities': 'None'},
        {'alignment': 'Neutral'},
        {'size': 'Medium'},
        {'speed': 6},
        {'languages': 'Common'},
        {'ability_modifiers': {
            {'str': 1},
            {'dex': 1},
            {'con': 1},
            {'int': 1},
            {'wis': 1},
            {'cha': 1}}}
    },
    'Dwarf': {
        {'abilities': [
            'ability1',
            'ability2'
            ]},
        {'alignment': 'Lawful Good'},
        {'size': 'Medium'},
        {'speed': 5},
        {'languages': [
            'Common',
            'Dwarven'
            ]},
        {'ability_modifiers': [
            {'con': 2},
            {'wis': 1}
            ]}
    },
    'Elf': {
        {'abilities': [
            'ability1',
            'ability2'
            ]},
        {'alignment': 'Chaotic Good'},
        {'size': 'Medium'},
        {'speed': 6},
        {'languages': [
            'Common',
            'Elven'
            ]},
        {'ability_modifiers': [
            {'dex': 2},
            {'int': 1}
            ]}
    }
},
'classes': {
    {'Fighter': {}},
    {'Ranger': {}},
    {'Wizard': {}}
},
'ability_scores': [
    {'Str': 'str'},
    {'Dex': 'dex'},
    {'Con': 'con'},
    {'Int': 'int'},
    {'Wis': 'wis'},
    {'Cha': 'cha'}]
}

I am simply trying to create the dictionary, not calling any keys from it.

As I understand from TypeError: unhashable type: 'dict' , I can use frozenset() to get keys.

Is there a better way to do what I am trying to do?

Community
  • 1
  • 1
Steven Pincé
  • 51
  • 1
  • 1
  • 6
  • 3
    [TypeError: unhashable type: 'dict'](http://stackoverflow.com/questions/13264511/typeerror-unhashable-type-dict), [Error: unhashable type: 'dict'](http://stackoverflow.com/questions/32295767/error-unhashable-type-dict), [unhashable type: 'dict' Type Error](http://stackoverflow.com/questions/27435798/unhashable-type-dict-type-error). Do you need more?... – Delgan Nov 07 '15 at 09:02
  • I'm not calling any keys, just making the dictionary. Is it impossible to have nested dictionaries like this? – Steven Pincé Nov 07 '15 at 09:06
  • 1
    It is impossible because dictionnary's keys have to be hashable, and dictionnary themself are not (because it is mutable). So if you try to create a dictionnary with dictionnaries as keys, it while raise this kind of error. – Delgan Nov 07 '15 at 09:08
  • `core_phb = { 'races': { 'Human': { {'abilities': 'None'}, {'alignment': 'Neutral'}...`. A dict that use dict as key and no value?`'Human': { {'abilities': 'None'}` – Remi Guan Nov 07 '15 at 09:14
  • Possible duplicate of [TypeError: unhashable type: 'dict', when dict used as a key for another dict](http://stackoverflow.com/questions/4531941/typeerror-unhashable-type-dict-when-dict-used-as-a-key-for-another-dict) – sds Nov 07 '16 at 15:59

3 Answers3

5

You seem to be making dictionaries {...} incorrectly for Python.

Lists look like this:

[ {'a': 1}, {'b': 1}, {'c': 1} ]

Dictionaries look like this:

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

If I'm guessing the behavior you want correctly, then you probably wanted something like this:

human = {
    'abilities': 'None',
    'alignment': 'Neutral',
    'size': 'Medium',
    'speed': 6,
    'languages': 'Common',
    'ability_modifiers': {
        'str': 1,
        'dex': 1,
        'con': 1,
        'int': 1,
        'wis': 1,
        'cha': 1
    }
}
John Starich
  • 619
  • 11
  • 15
4

The problem is not with the dicts, but with the sets. The elements of a set must be hashable. In

core_phb = {
'races': {
    'Human': {
        {'abilities': 'None'},
        {'alignment': 'Neutral'},
        {'size': 'Medium'},
        {'speed': 6},
        {'languages': 'Common'},
        {'ability_modifiers': {
            {'str': 1},
            {'dex': 1},
            {'con': 1},
            {'int': 1},
            {'wis': 1},
            {'cha': 1}}}
    },
    'Dwarf': {
        {'abilities': [
            'ability1',
            'ability2'
            ]},
        {'alignment': 'Lawful Good'},
        {'size': 'Medium'},
        {'speed': 5},
        {'languages': [
            'Common',
            'Dwarven'
            ]},
        {'ability_modifiers': [
            {'con': 2},
            {'wis': 1}
            ]}
    },
    'Elf': {
        {'abilities': [
            'ability1',
            'ability2'
            ]},
        {'alignment': 'Chaotic Good'},
        {'size': 'Medium'},
        {'speed': 6},
        {'languages': [
            'Common',
            'Elven'
            ]},
        {'ability_modifiers': [
            {'dex': 2},
            {'int': 1}
            ]}
    }
},
'classes': {
    {'Fighter': {}},
    {'Ranger': {}},
    {'Wizard': {}}
},
'ability_scores': [
    {'Str': 'str'},
    {'Dex': 'dex'},
    {'Con': 'con'},
    {'Int': 'int'},
    {'Wis': 'wis'},
    {'Cha': 'cha'}]
}

the key is fine, but the value is an illegal set, because its elements are dicts. You could make frozensets from the sets and you'd be OK.

{frozenset({1})}
{frozenset({1})}
{{1}}
Traceback (most recent call last):
  Python Shell, prompt 7, line 1
builtins.TypeError: unhashable type: 'set'
saulspatz
  • 5,011
  • 5
  • 36
  • 47
2

I think this :

'Human': {
    {'abilities': 'None'},
    {'alignment': 'Neutral'},
    {'size': 'Medium'},
    {'speed': 6},
    {'languages': 'Common'},
    {'ability_modifiers': {
        {'str': 1},
        {'dex': 1},
        {'con': 1},
        {'int': 1},
        {'wis': 1},
        {'cha': 1}}}
},

should be a list. Otherwise, each of the comma-separated elements is a mutable element which you are trying to store in a set. You are already doing it right with the very last entry:

'ability_scores': [
{'Str': 'str'},
{'Dex': 'dex'},
{'Con': 'con'},
{'Int': 'int'},
{'Wis': 'wis'},
{'Cha': 'cha'}]

so why not all the others?

Dmitry Rubanovich
  • 2,471
  • 19
  • 27