Python中是否有对象唯一标识符


77

这将类似于该java.lang.Object.hashcode()方法。

我需要将无法控制的对象存储在一个集中,并确保只有两个对象实际上是同一对象(不包含相同的值)时,这些值才会被覆盖。


6
请注意,hashCode()在Java中不一定是唯一的,它只是结合了一些经过精心选择的语义equals()
乔伊,

1
正如下面贴了Python的hash()具有确切相同的语义java.lang.Object.hashcode()
ilya n。

Answers:


124
id(x)

会帮你的忙。但我很好奇,对象集(按值组合对象)有什么问题?

对于您的特定问题,我可能会保留一组ID或包装对象。包装对象将包含一个引用,并按x==y<==>进行比较x.ref is y.ref

还值得注意的是,Python对象也具有hash功能。此功能对于将对象放入集合或字典是必需的。它有时会因不同的对象而发生冲突,尽管hash尝试使它的可能性降低的良好实现。


3
拒绝投票,因为id(x)不能确保每个对象的唯一性。OP非常清楚,他/她想将包含相同值的不同对象视为不同
罗伊

12
相反@Roy的文档id(x) “保证是其一生中唯一的和恒定的此对象”,这将导致与具有不同ID的相同的值不同的对象(只要它们在同一时间同时存在),这将使OP能够做他们想要的事情。
sparrowt

3
@sparrowt我明白了。我同意你。关键是“当两个具有相同值的对象共存时,ID是唯一的”。id()似乎为具有相同值的重复创建(和销毁)的对象返回相同的ID,因此是我的原始评论,但实际上这很好,因为OP声明当这些对象共存时ID必须是唯一的。删除我的不赞成票。
罗伊

啊,现在不能更改我的投票,为时已晚。很抱歉造成混乱和投票错误(诚实的错误)。
罗伊(Roy)

1
x.ref在将包装器x分配给变量之后,在这种情况下,@ flow2k将是包装器中包含对原始属性的引用的属性的名称x
Qwertronix

31

这就是“ is”的目的。

与其测试“ if a == b”来测试相同的值,

测试“ if a is b”,它将测试相同的标识符。


20
准确地说Python的“是”就像Java的“ ==”,Python的“ ==”就像Java的“ equals()”一样准确吗?
MatrixFrog,2009年

12
@MatrixFrog是的。
Imagist

2

正如ilya n所提到的,id(x)为对象生成唯一的标识符。

但是您的问题令人困惑,因为Java的hashCode方法没有提供唯一的标识符。Java的hashCode就像大多数哈希函数一样工作:它始终为同一个对象返回相同的值,两个相等的对象始终返回相等的代码,不相等的哈希值表示不相等的哈希码。特别是,两个不同且不相等的对象可以获得相同的值。

这是令人困惑的,因为加密哈希函数与此完全不同,并且更像(尽管不完全是)您所要求的“唯一ID”。

Java的hashCode方法的Python等效项是hash(x)。


这就是为什么我明确提到java.lang.Object的hashcode方法的原因。默认情况下,它为该对象生成唯一的long。我意识到哈希码的其他实现可以而且确实会有所不同。
自己

但这就是重点:hashCode不会产生唯一的long。它产生的long会努力避免冲突,但是您不能将字符串映射到long并产生唯一的值。
Ned Batchelder

1
...我知道的旧线程。但是我确实想指出,id()仅在两个对象仍然存在时才是唯一的。一旦释放,就可以将ID分配给“每个具有不重叠生存期的对象可以具有相同的id()值”的每个对象。 链接
罗伯特·拉格

但是在Pythonhash(.)中不适用于列表...我知道列表是可变的,但我只需要根据列表的内容生成一个数字。也许sum(myList),作为一个较差的哈希函数...
flow2k

-1

您不必先比较对象,再将它们放在集合中。set()语义已经解决了这一问题。

   class A(object): 
     a = 10 
     b = 20 
     def __hash__(self): 
        return hash((self.a, self.b)) 

   a1 = A()
   a2 = A()
   a3 = A()
   a4 = a1
   s = set([a1,a2,a3,a4])
   s
=> set([<__main__.A object at 0x222a8c>, <__main__.A object at 0x220684>, <__main__.A object at 0x22045c>])

注意:您实际上不必重写哈希 即可证明此行为:-)


2
您的解决方案取决于继承自的类的类型:class B(str): pass如果使用set([B(), B()])导致调用set([''])。从字典中进行识别通常隐含地依赖于id(x)对象,您应该只显式地使用它并避免出现极端情况。
Arne 2015年

@ArneRecknagel你是对的。但是在检查id(x)之​​后,您将把什么放入集合中?
user942640 '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.