不可变类型的ID

3 投票
4 回答
961 浏览
提问于 2025-04-16 07:41

我对可变对象和不可变对象之间的区别有点困惑。我试着运行了一段代码来找出对象的ID:

tuple1 = ('Object1', 'Object2')
print id(tuple1)
tuple2 = ('Object1', 'Object2')
print id(tuple2)
list1 = ['Object1', 'Object2']
print id(list1)
list2 = ['Object1', 'Object2']
print id(list2)
string1 = "Foo bar"
print id(string1)
string2 = "Foo bar"
print id(string2)

我发现字符串的ID是一样的,列表的ID是不同的,而元组的ID也不同。难道它们不应该有相同的ID吗?我想知道这个是怎么回事?

谢谢

4 个回答

1

不可变的意思是你不能改变这个类的实例。举个例子:

salad = ["Lettuce","Tomato","Onion","Tuna"]
fruit = ("Apple","Banana","Cherry","Fig","Grapefruit")
salad[3] = "Cheese"   # works
fruit[3] = "Orange"   # error message
3

你会发现字符串的ID是一样的,因为字符串字面量可以被“内部化”。而元组的ID就不一样,因为元组是不能被内部化的。

一个可变的数据结构是不能被合理地内部化的(换句话说,内部化会导致非常混乱的行为),所以如果字符串是可变的,它们就不能被内部化。不过,这并不意味着所有不可变的数据结构都是内部化的。

5

相同的ID意味着是完全相同的对象,但Python的实现可以自由地优化不可变对象的创建方式。例如,在CPython 2.6.6中,小整数对象是被缓存的,所以:

>>> x=256
>>> x is 256
True
>>> x=1024
>>> x is 1024
False

[NOTE: 'is' tests for object identity (same ID)]

这并不意味着在其他实现中结果也会一样。某个实现可能会缓存不可变的元组,但哪些元组是常见的呢?如果像你说的那样,所有相同的元组返回相同的ID,那么程序创建的每个元组都必须被缓存,每次新创建一个元组时都得去缓存中查找一下之前是否已经创建过,这样会很耗时间。

使用==来测试对象是否相等,而不管它们的ID是什么。

撰写回答