2013-10-08 83 views
1

我試圖減少我的代碼中的複製/粘貼,並且偶然發現了這個問題。我已經搜索了答案,但所有的答案都使用一個類的實例作爲關鍵,我找不到任何關於使用類定義本身作爲關鍵(我不知道是否有可能)。是否有可能在Python 3中使用類作爲字典鍵?

我的代碼是這樣的:

# 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 

和錯誤是這樣

TypeError: unhashable type: 'Assignment' 

下面是類定義:

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])),')' 

是否有任何替代方法,我可以用獲得相同的效果?

謝謝。

+0

只要這些類是可散的,它就可以工作。你試過了嗎?發生了什麼? – SethMMorton

+0

@SethMMorton我更新了問題以顯示錯誤和我正在使用的代碼,對於過早的帖子感到抱歉。 – PudgePacket

+0

你應該看看這個帖子:http://stackoverflow.com/questions/7152497/making-a-python-user-defined-class-sortable-hashable。看看第二個答案的後半部分。如果它不可散列,則不能將其用作字典密鑰。 – SethMMorton

回答

6

確定,評論失控;-)

現在的似乎是確定類對象不是問題。如果是這樣,錯誤將引發對第一線,當第一次構建了字典:

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

如果你試圖建立一個字典與unhashable鍵,字典創建失敗一次:

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

但是你超越了那條線,Assignment是你構造的字典的關鍵。因此,錯誤是在這一行:

 localScope = chunkFuncs[chunk](chunk,localScope) 

最好的猜測是,它是一個實例Assignment這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' 

看到了嗎? mylist是可散列的,但實例mylist()不是。

後來:最好的猜測是你不會對此有所w w。爲什麼?由於基類名稱pyPeg.List。如果它像Python列表一樣可變,那麼實例將不可散列 - 並且不應該是(可變對象總是像dict鍵一樣危險)。你仍然可以通過id(the_instance)索引一個字典,但是否在語義上是否正確是我不知道更多關於你的代碼的猜測。

+0

你是對的,我在閱讀你的回覆後發現的解決方案是使用找到前一個isinstance()調用的類型作爲字典鍵而不是類型本身的實例。簡單的錯誤,但所有其他的複雜性使它滑過。謝謝 ! – PudgePacket

1

你應該是可以的,是的,但你可能需要一個額外的type電話:

>>> class X: 
...  pass 
... 
>>> class_map = {X: 5} 
>>> my_x = X() 
>>> class_map[type(my_x)] 
5 
相關問題