Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use a class as a dictionary key in Python 3?

I'm trying to reduce copy/paste in my code and have stumbled upon this problem. I've googled for the answer but all answers use an instance of a class as the key, I can't find anything on using a class definition itself as the key (I don't know if it's possible).

My code is this:

# All chunkFuncs keys are class definitions, all values are functions
chunkFuncs = {Math_EXP : Math_EXPChunk, Assignment : AssignmentChunk, Function : FunctionChunk}

def Chunker(chunk, localScope):
    for chunkType in chunkFuncs:
        if isinstance(chunk,chunkType):
            # The next line is where the error is raised
            localScope = chunkFuncs[chunk](chunk,localScope)
            return localScope

and the error is this

TypeError: unhashable type: 'Assignment'

Here are the class definitions:

class Math_EXP(pyPeg.List):
    grammar = [Number,Symbol],pyPeg.maybe_some(Math_OP,[Number,Symbol])

class Assignment(pyPeg.List):
    grammar = Symbol,'=',[Math_EXP,Number]

class Function(pyPeg.List):
    grammar = Symbol,'(',pyPeg.optional(pyPeg.csl([Symbol,Number])),')'

Are there any alternative methods I could use to get the same effect?

Thanks.

like image 365
Trent Avatar asked Oct 08 '13 04:10

Trent


People also ask

Can class be a key in dictionary Python?

Yes, only when getting, not setting. Edited: KeyError. @Sergey: You will have to tell us more about class A . Did you overwrite any special methods?

Can you use an object as a key in a Python dictionary?

Dictionaries in PythonAlmost any type of value can be used as a dictionary key in Python. You can even use built-in objects like types and functions.

What Cannot be used as a key in a Python dictionary?

We can use integer, string, tuples as dictionary keys but cannot use list as a key of it .

What can be used as a key in Python dictionary?

Strings, numbers, and tuples work as keys, and any type can be a value. Other types may or may not work correctly as keys (strings and tuples work cleanly since they are immutable). Looking up a value which is not in the dict throws a KeyError -- use "in" to check if the key is in the dict, or use dict.


1 Answers

OK, the comments are getting out of hand ;-)

It seems certain now that the class object isn't the problem. If it were, the error would have triggered on the first line, when the dict was first constructed:

chunkFuncs = {Math_EXP : Math_EXPChunk, Assignment : AssignmentChunk, Function : FunctionChunk}

If you try to construct a dict with an unhashable key, the dict creation fails at once:

>>> {[]: 3}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

But you got beyond that line, and Assignment is a key in the dict you constructed. So the error is in this line:

        localScope = chunkFuncs[chunk](chunk,localScope)

Best guess is that it's an instance of Assignment that's unhashable:

>>> class mylist(list):
...   pass
...
>>> hash(mylist)
2582159
>>> hash(mylist())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'mylist'

See? mylist is hashable, but the instance mylist() is not.

Later: best guess is that you're not going to be able to worm around this. Why? Because of the name of the base class, pyPeg.List. If it's mutable like a Python list, then instances won't be hashable - and shouldn't be (mutable objects are always dangerous as dict keys). You could still index a dict by id(the_instance), but whether that's semantically correct is something I can't guess without knowing a lot more about your code.

like image 161
Tim Peters Avatar answered Nov 03 '22 23:11

Tim Peters