我可以使用对象(类的实例)作为 Python 中的字典键吗?
Posted
技术标签:
【中文标题】我可以使用对象(类的实例)作为 Python 中的字典键吗?【英文标题】:Can I use an object (an instance of a class) as a dictionary key in Python? 【发布时间】:2011-11-25 11:41:25 【问题描述】:我想使用类实例作为字典键,例如:
classinstance = class()
dictionary[classinstance] = 'hello world'
Python 似乎无法将类作为字典键处理,还是我错了? 此外,我可以使用像 [(classinstance, helloworld),...] 这样的元组列表来代替字典,但这看起来很不专业。 你有任何解决这个问题的线索吗?
【问题讨论】:
没问题 - 它对我来说很好用。为什么你认为它不起作用 - 你有任何例外吗?你有什么python版本? 我使用 Python 2.7 + twisted 框架。此消息显示在我身上:exceptions.KeyError: <__main__.xmpp instance at> 所以 - 我有信心(或者只是这么认为)这个异常不是在你将元素添加到 dict 时引发的(就像在你的例子中一样)但是当你尝试获取它时 - 检查你放了什么在它之前 - 您用作键的实例可能已更改。 是的,它似乎发生了,我想删除它。正在检查一些细节... 当我尝试获取它时也会发生这种情况。 【参考方案1】:您的实例需要是可散列的。 python glossary 告诉我们:
如果一个对象的哈希值在其生命周期内永远不会改变(它需要
__hash__()
方法),并且可以与其他对象进行比较(它需要__eq__()
或__cmp__()
方法),则它是可哈希的。比较相等的可散列对象必须具有相同的散列值。哈希性使对象可用作字典键和集合成员,因为这些数据结构在内部使用哈希值。
所有 Python 的不可变内置对象都是可散列的,而没有可变容器(例如列表或字典)是可散列的。默认情况下,作为用户定义类实例的对象是可散列的;它们都比较不相等,它们的hash值就是它们的id()。
【讨论】:
这是正确的,但具有误导性。默认情况下,所有对象实例都是可散列的。哈希码将是对象实例的唯一标识符。 "他们的哈希值是他们的 id()。"这在 python3.x 之后发生了变化,请参阅 ***.com/a/11324771/2135504【参考方案2】:尝试在您的类中实现 hash 和 eq 方法。
例如,这是我制作的一个简单的可散列字典类:
class hashable_dict:
def __init__(self, d):
self.my_dict = d
self.my_frozenset = frozenset(d.items())
def __getitem__(self, item):
return self.my_dict[item]
def __hash__(self):
return hash(self.my_frozenset)
def __eq__(self, rhs):
return isinstance(rhs, hashable_dict) and self.my_frozenset == rhs.my_frozenset
def __ne__(self, rhs):
return not self == rhs
def __str__(self):
return 'hashable_dict(' + str(self.my_dict) + ')'
def __repr__(self):
return self.__str__()
【讨论】:
KISS : 保持简单 S* :-) 我认为 ltsstar 不需要这种复杂的代码。 我不同意。我认为编写一个放入字典的类的示例可能非常有用。对于初学者来说,字典似乎很神奇,理解为什么对象会以相同/不同的方式散列对象以确保您的代码按预期工作非常重要。你和我可能只是有不同的个人品味,但我总是喜欢例子,尤其是在 15 行左右的时候。 :)【参考方案3】:使用实例作为字典键没有任何问题,只要它遵循the rules:字典键必须是不可变的。
【讨论】:
同样的问题,最好用元组什么的? 很难说元组更好。元组更简单。但是,如果您需要将实例存储为字典键,那可能对您更好,但也更复杂。 :)【参考方案4】:以下代码运行良好,因为默认情况下,您的类对象是可散列的:
Class Foo(object):
def __init__(self):
pass
myinstance = Foo()
mydict = myinstance : 'Hello world'
print mydict[myinstance]
输出: 世界你好
另外和更高级的用法,你应该阅读这篇文章:
Object of custom type as dictionary key
【讨论】:
以上是关于我可以使用对象(类的实例)作为 Python 中的字典键吗?的主要内容,如果未能解决你的问题,请参考以下文章