代码之家  ›  专栏  ›  技术社区  ›  badp

在python中,“a is b”和“id(a)==id(b)”有什么区别?

  •  33
  • badp  · 技术社区  · 15 年前

    这个 id() 内置函数给出…

    一个整数(或长整数),在该对象的生存期内,该整数保证是唯一的和常量。

    这个 is 相反,操作员给出…

    对象标识

    为什么有两个相同的物体 id 但归来 False 检查?下面是一个例子:

    >>> class Test():
    ...   def test():
    ...     pass
    >>> a = Test()
    >>> b = Test()
    >>> id(a.test) == id(b.test)
    True
    >>> a.test is b.test
    False
    

    一个更麻烦的例子:(继续上面的内容)

    >>> b = a
    >>> b is a
    True
    >>> b.test is a.test
    False
    >>> a.test is a.test
    False
    

    然而:

    >>> new_improved_test_method = lambda: None
    >>> a.test = new_improved_test_method
    >>> a.test is a.test
    True
    
    1 回复  |  直到 15 年前
        1
  •  55
  •   Mike Graham    15 年前
    >>> b.test is a.test
    False
    >>> a.test is a.test
    False
    

    方法在每次查找时都是即时创建的。函数对象(始终是同一对象)实现 descriptor protocol 及其 __get__ 创建绑定方法对象。通常没有两个绑定方法是相同的对象。

    >>> id(a.test) == id(b.test)
    True
    >>> a.test is b.test
    False
    

    这个例子是有欺骗性的。第一个结果只是 True 巧合。 a.test 创建一个绑定方法,它在计算后被垃圾收集 id(a.test) 因为没有任何参考。(请注意,您引用的文档中说,ID对于此对象是“唯一和常量” 在它的一生中 “(强调我的)。” b.test 发生 与以前的绑定方法具有相同的ID,并且允许这样做,因为现在没有其他对象具有相同的ID。

    注意你应该很少使用 is 更不用说经常使用 id . id(foo) == id(bar) 总是错的。


    关于您的新示例,希望您现在能够了解它的功能:

    >>> new_improved_test_method = lambda: None
    >>> a.test = new_improved_test_method
    >>> a.test is a.test
    True
    

    在这种情况下,我们不会让类上的函数中的方法自动绑定自己并返回绑定的方法对象。在这种情况下,只需将函数存储为实例属性。查找时不会发生任何特殊情况(只有在查找类属性时才会调用描述符),因此每次查找属性时,都会获取存储的原始对象。