Python 不可变类型 ID 和 if 语句
Python immutable type ids and the is statment
我认为下面的所有内容都会评估为 False。有人可以解释发生了什么吗?不可变构造函数不会创建新对象(和新 ID)吗?元组如何具有相同的id并且是不同的对象?
print((1,) is (1,))
print(id(1,) == id(1,))
print('a' is 'a')
print(id('a') == id('a'))
结果:
False
True
True
True
您使用元组的每个实例构造一个不可变类型的新实例。元组的值不能改变,但它们是不同的(虽然相等)实例。
你的第二行不正确。您正在将 1
传递给 id
。 (Python 允许在参数列表中使用尾随逗号。)
print((1,) is (1,))
print(id((1,)) == id((1,)))
print('a' is 'a')
print(id('a') == id('a'))
哪些是
False
False
True
True
所以 id
和 is
的结果匹配。
请注意,is
/id
的结果可能因实施而异。
例如,在 CPython 2.7 中,2 * 2 is 4
但 2 * 200 is not 400
。对于低整数值,CPython 使用相同的内存地址(这是 CPython 中 id
的结果)。同样,这因实施而异。
您可能会在 Python、Java 和其他对象中使用不可变对象看到 interning 的结果。
PEP237 状态:
- 具有小值的短整数(通常在 -1 到 99 之间
inclusive) 是 "interned" -- 只要结果有这样的值,
返回具有相同值的现有 short int。这是
没有为具有相同值的长整数完成。这个区别
会保持。 (由于不能保证这次实习,是
这是否是语义差异值得商榷——但代码
可能存在使用 'is' 比较短整数和
正好因为这次实习工作。这样的代码可能会失败
如果与长整数一起使用。)
示例:
>>> x=7
>>> y=10-3
>>> z=int('7')
>>> all(7 is e for e in [x,y,z])
True
>>> map(id, [x,y,z])
[140410571769784, 140410571769784, 140410571769784]
字符串:
>>> s1='abc'
>>> s2='abc'
>>> s1 is s2
True
>>> id(s1)
4378429560
>>> id(s2)
4378429560
您不能依赖不可变对象的实例作为该对象的唯一标签。它是一个实现细节,可能因版本和实现而异。
print((1,) is (1,))
print(id(1,) == id(1,))
print('a' is 'a')
print(id('a') == id('a'))
1- 首先评估为 false 因为 2 个元组是不同的对象
2- 它的计算结果为真,因为 id(1,)
不将 1,
识别为元组,而只是将其识别为 1,并且当您有小整数或字符串时,python 执行优化将 2 个名称引用到相同的 id,因此它不必分配 2 个不同的空间。如果你有 id((1,))
那将是错误的,因为它会把它识别为一个元组
3 和 4 - 它们为真,原因与 2 为真相同
我认为下面的所有内容都会评估为 False。有人可以解释发生了什么吗?不可变构造函数不会创建新对象(和新 ID)吗?元组如何具有相同的id并且是不同的对象?
print((1,) is (1,))
print(id(1,) == id(1,))
print('a' is 'a')
print(id('a') == id('a'))
结果:
False
True
True
True
您使用元组的每个实例构造一个不可变类型的新实例。元组的值不能改变,但它们是不同的(虽然相等)实例。
你的第二行不正确。您正在将 1
传递给 id
。 (Python 允许在参数列表中使用尾随逗号。)
print((1,) is (1,))
print(id((1,)) == id((1,)))
print('a' is 'a')
print(id('a') == id('a'))
哪些是
False
False
True
True
所以 id
和 is
的结果匹配。
请注意,is
/id
的结果可能因实施而异。
例如,在 CPython 2.7 中,2 * 2 is 4
但 2 * 200 is not 400
。对于低整数值,CPython 使用相同的内存地址(这是 CPython 中 id
的结果)。同样,这因实施而异。
您可能会在 Python、Java 和其他对象中使用不可变对象看到 interning 的结果。
PEP237 状态:
- 具有小值的短整数(通常在 -1 到 99 之间 inclusive) 是 "interned" -- 只要结果有这样的值, 返回具有相同值的现有 short int。这是 没有为具有相同值的长整数完成。这个区别 会保持。 (由于不能保证这次实习,是 这是否是语义差异值得商榷——但代码 可能存在使用 'is' 比较短整数和 正好因为这次实习工作。这样的代码可能会失败 如果与长整数一起使用。)
示例:
>>> x=7
>>> y=10-3
>>> z=int('7')
>>> all(7 is e for e in [x,y,z])
True
>>> map(id, [x,y,z])
[140410571769784, 140410571769784, 140410571769784]
字符串:
>>> s1='abc'
>>> s2='abc'
>>> s1 is s2
True
>>> id(s1)
4378429560
>>> id(s2)
4378429560
您不能依赖不可变对象的实例作为该对象的唯一标签。它是一个实现细节,可能因版本和实现而异。
print((1,) is (1,))
print(id(1,) == id(1,))
print('a' is 'a')
print(id('a') == id('a'))
1- 首先评估为 false 因为 2 个元组是不同的对象
2- 它的计算结果为真,因为 id(1,)
不将 1,
识别为元组,而只是将其识别为 1,并且当您有小整数或字符串时,python 执行优化将 2 个名称引用到相同的 id,因此它不必分配 2 个不同的空间。如果你有 id((1,))
那将是错误的,因为它会把它识别为一个元组
3 和 4 - 它们为真,原因与 2 为真相同