首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Python中使用的是比较id吗?字典键比较?

问在Python中使用的是比较id吗?字典键比较?
EN

Stack Overflow用户
提问于 2012-09-21 22:00:14
回答 3查看 468关注 0票数 2

这是什么意思?

唯一不能作为字典键接受的值类型是包含列表或字典或其他可变类型的值,这些值按值而不是按对象标识进行比较,原因是字典的有效实现要求键的散列值保持不变。

我认为,即使是元组,也会按价值进行比较。

EN

回答 3

Stack Overflow用户

发布于 2012-09-21 22:03:03

可变对象作为密钥的问题是,当我们使用字典时,我们很少想检查标识。例如,当我们使用这样的字典时:

代码语言:javascript
复制
a = "bob"
test = {a: 30}
print(test["bob"])

我们希望它能工作--第二个字符串"bob"可能与a不一样,但它是相同的值,这正是我们所关心的。这是因为任何两个相等的字符串都有相同的散列,这意味着dict (作为hashmap实现)可以非常有效地查找这些字符串。

当我们有一个清单作为关键时,这个问题就会起作用,想象一下这个例子:

代码语言:javascript
复制
a = ["bob"]
test = {a: 30}
print(test[["bob"]])

我们不能再这样做了--比较不能工作,因为列表的散列不是基于它的值,而是基于列表的实例(又名(id(a) != id(["bob")))。

Python可以选择更改列表的散列(破坏hashmap的效率)或简单地比较身份(在大多数情况下这是无用的)。Python不允许这些特定的可变键来避免微妙但常见的but,因为人们期望在值上而不是在标识上将值等同起来。

票数 6
EN

Stack Overflow用户

发布于 2012-09-21 22:38:03

文档将两种不同的东西混合在一起:可变性和价值可比较性。我们把它们分开。

  • 按身份进行比较的不可变对象很好。对于任何物体来说,身份是永远不会改变的。
  • 按值进行比较的不可变对象很好。不可变对象的值永远不会更改。这包括元组。
  • 根据身份进行比较的可变对象是可以的。对于任何物体来说,身份是永远不会改变的。
  • 根据值进行比较的可变对象是不可接受的。值可以更改可变对象,这将使字典无效。

同时,您的措辞与映射类型(4.10 Python 3.3或5.8在Python 2.7中 )并不完全相同,这两种类型都说:

字典的键几乎是任意的值。不可接受的值,即包含列表、字典或其他可变类型(按值而不是按对象标识进行比较)的值不能用作键。

无论如何,这里的关键点是,规则是“不可理解的”;“可变类型(通过值而不是对象标识进行比较)”只是为了进一步解释。严格地说,按对象标识进行比较和按对象标识进行散列总是不一样的(唯一需要的是,如果id是相等的,则哈希是相等的)。

您发布的版本中关于“字典的有效实现”的部分只会增加混乱(这可能是参考文档中没有的原因)。即使有人想出了一种有效的方法来处理明天将列表作为切分键存储的问题,但语言不允许这样做。

票数 1
EN

Stack Overflow用户

发布于 2012-09-21 22:27:47

散列是为对象计算唯一代码的方法,对于同一对象,此代码总是相同的。例如,hash('test')是2314058222102390712,a=‘test’也是;hash(a) = 2314058222102390712。

在内部,字典值由哈希搜索,而不是通过指定的变量搜索。列表是可变的,列表的散列(如果已定义)将在列表更改时进行更改。因此,python的设计没有散列列表。因此,列表不能用作字典键。

元组是不可变的,因此tuble有散列,例如hash((1,2)) = 3713081631934410656。可以通过比较散列而不是值来比较元组a是否等于元组(1,2)。这将是更有效的,因为我们只能比较一个值,而不是两个。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12538723

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档