【问题标题】:Is it possible to use a class as a dictionary key in Python 3?是否可以在 Python 3 中使用类作为字典键?
【发布时间】:2013-10-14 20:42:39
【问题描述】:

我正在尝试减少代码中的复制/粘贴,但偶然发现了这个问题。我已经搜索了答案,但所有答案都使用类的实例作为键,我找不到使用类定义本身作为键的任何内容(我不知道是否可能)。

我的代码是这样的:

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

我可以使用其他方法来获得相同的效果吗?

谢谢。

【问题讨论】:

  • 只要类是可散列的,它就可以工作。你试过了吗?发生了什么?
  • @SethMMorton 我更新了问题以显示错误和我正在使用的代码,对于过早的帖子感到抱歉。
  • 你应该看看这篇文章:stackoverflow.com/questions/7152497/…。查看第二个答案的后半部分。如果您的类不可散列,则不能将其用作字典键。
  • pyPeg.List 是从哪里来的?发生了一些奇怪的事情。也许pyPeg 是一个过于花哨的;-) 框架玩元类游戏 - 你必须努力使类对象不可散列。
  • 顺便说一句,您没有显示回溯:确切地说,哪一行触发了TypeError?而且,是的,您可以使用id(some_class_object) 作为字典键。

标签: python hash dictionary python-3.x


【解决方案1】:

好的,cmets 已经失控了 ;-)

现在看来,类对象不是问题所在。如果是这样,错误将在 first 行触发,即第一次构造 dict 时:

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

如果您尝试使用不可散列的键构造字典,则字典创建会立即失败:

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

但是你已经超出了这条线,Assignment 是你构建的字典中的一个键。所以错误就在这一行:

        localScope = chunkFuncs[chunk](chunk,localScope)

最好的猜测是它是Assignment 的一个实例,它是不可散列的:

>>> 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() 不是。

稍后:最好的猜测是您将无法绕开这个问题。为什么?由于基类的名称pyPeg.List。如果它像 Python 列表一样是可变的,那么实例就不会是可散列的——也不应该是可散列的(可变对象作为 dict 键总是危险的)。你仍然可以通过id(the_instance) 索引一个字典,但如果不了解更多关于你的代码,我无法猜测这在语义上是否正确。

【讨论】:

  • 你是对的,我在阅读你的回复后找到的解决方案是使用找到之前 isinstance() 调用的类型作为 dict 键而不是类型本身的实例。一个简单的错误,但所有其他的复杂性让它溜走了。谢谢!
【解决方案2】:

你应该可以,是的,但你可能需要额外的type 电话:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-18
    • 2018-03-30
    • 1970-01-01
    • 2011-10-25
    • 2014-04-14
    • 2013-12-03
    • 2017-05-06
    • 2023-04-06
    相关资源
    最近更新 更多