整数文字的奇怪行为

时间:2014-10-30 13:06:34

标签: python python-2.7

我不了解此代码的行为:

a = hash((10,)), hash((10,))
# a is 3430012387537 is 3430012387537  Note it can be different for you but they are same integers

a[0] is a[1]
# Gives False


3430012387537 is 3430012387537
# Gives True

为什么第一次测试会给出False而第二次给出True

它似乎是由大整数引起的,因为10个按预期工作:

a = 10, 10
a[0] is a[1]
# Gives True as expected

3 个答案:

答案 0 :(得分:7)

您正在观察Python解释器的实现细节 - 这就是有些人可能无法重现此问题的原因。

Intepreter可能会决定

  • 每次看到整数
  • 时创建int的新实例
  • 保留一些常见值的实例(例如-10,..,255
  • 每次看到一个整数时创建一个新实例,然后保留它(永久或一段时间)
  • 上述任何组合

您永远不应该依赖于解释器实现细节,因此您不应该依赖x is y来获取整数。

答案 1 :(得分:5)

您正在测试元组的哈希值。如果两个对象是a)相等并且b)支持散列,那么它们的散列值必须是相同的。

这并不意味着它们是同一个对象,只是它们具有相同的哈希值。没有更多,没有更少。哈希值甚至不必是唯一的,并且具有相同哈希值的两个对象也不必相等;该财产不具有传递性。

来自__hash__ method documentation

  

唯一需要的属性是比较相等的对象具有相同的哈希值;建议以某种方式将对象组件的哈希值混合在一起(例如使用exclusive或),这些哈希值也是对象比较中的一部分。

接下来,你正在做一些完全不同的事情,你正在比较同一个表达式中的两个文字是否相同。当然,在这种情况下,编译器不会通过创建两个单独的对象来浪费内存:

>>> import dis
>>> dis.dis(compile('3430012387537 is 3430012387537', '<stdin>', 'exec'))
  1           0 LOAD_CONST               0 (3430012387537)
              3 LOAD_CONST               0 (3430012387537)
              6 COMPARE_OP               8 (is)
              9 POP_TOP
             10 LOAD_CONST               1 (None)
             13 RETURN_VALUE

LOAD_CONST字节码加载相同的对象(索引0处的常量)。

这并不意味着Python解释器中的每个表达式都将重用常量,只需在这个方法中处理在一个块中编译的所有内容。这意味着同一函数中的文字也可能最终重用相同的常量对象。

底线是:当你真的想使用is时,请不要使用==; Python可能会或可能不会通过重用相同的对象来优化内存和执行速度,但并非所有相同的内容始终都是同一个对象。仅为单身人士保留is(例如None,输入对象,并明确创建单个实例)。

答案 2 :(得分:2)

这里发生的一切就是你的特定Python解释器在编译时检测到同一个整数文字出现多次。发生这种情况时,它只创建一个整数对象并重新使用它。任何计算这些数字的方法(可能是hash,可能只是123456789123456788+1)都不会得到相同的优化,因此您会看到不同的值。

当然,这只适用于你的翻译,另一个翻译可能表现不同。

Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:55:48) [MSC v.1600 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> 123456789123456789 is 123456789123456788+1
False
>>> hash((10,)) is hash((10,))
False

Python 2.7.2 (341e1e3821ff, Jun 07 2012, 15:43:00)
[PyPy 1.9.0 with MSC v.1500 32 bit] on win32
Type "help", "copyright", "credits" or "license" for more information.
And now for something completely different: ``the future has just begun''
>>>> 123456789123456789 is 123456789123456788+1
True
>>>> hash((10,)) is hash((10,))
True