我不了解此代码的行为:
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
答案 0 :(得分:7)
您正在观察Python解释器的实现细节 - 这就是有些人可能无法重现此问题的原因。
Intepreter可能会决定
int
的新实例
-1
,0
,..,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