为什么id([1] [::-1])== id([1])返回True,而[1] [::-1]是[1]返回False?

时间:2020-10-23 03:44:19

标签: python

我知道is运算符会比较两者的id,而不是值 但是为什么id([1][::-1])==id([1])返回True[1][::-1] is [1]返回False

id([1][::-1]) ==id([1]) #True
[1][::-1] is [1] #Fasle

id([1]) ==id([1][::-1])#Fasle
[1] is [1][::-1]#False

1 个答案:

答案 0 :(得分:2)

id([1][::-1]) ==id([1])True是CPython的一个古怪之处,它使用一个自由列表作为list的一个实现为堆栈的列表。第一个id([1][::-1])被完全求值,它产生的list在完成时被释放。当[1]为新的list分配空间时,它将在相同的地址处分配相同的内存,这在CPython中等效于其id

id仅在对象存在的情况下才保证是唯一的。由于原始的list在制作新的list之前就已经消失了,因此在相同的时间id上具有相同id的两个人都不会违反保证。

测试的顺序很重要,因为[1]本身是从小型对象分配器中最近释放的块集中提取的。这里的顺序是:

  1. 原始[::-1]被分配到地址A
  2. [1]的结果分配在地址B
  3. 此后,list分配A立即返回到id的空闲列表中
  4. int返回一个描述地址B的[::-1]
  5. [1]的结果B返回到空闲列表(在A之前)
  6. 分配第二个[::-1],得到id先前使用的内存B,
  7. id被调用,准确地产生与以前相同的[1](因为新的list被赋予了最近从产生的[::-1] list中释放出来的内存),因为两个id([1]) == id([1])都使用地址B

这实际上比需要的要复杂; list也会得到相同的结果(只会在list的空闲列表中留下少一些[1]。)

反之,则发生这种情况:

  1. id被分配到地址A
  2. int返回描述地址A的新[1]
  3. [1]被释放,地址A返回到池中
  4. 分配下一个[1],得到A,与第一个[::-1]相同的内存
  5. list应用于它,从新鲜的内存B中获得一个新的[1];然后id被丢掉
  6. [::-1]获得描述地址B的int的结果上调用
  7. id;地址A和B的list不匹配

如果您创建并存储了两个id,然后将仍然存在的list中的Boris, 1, Johnson Noah, 2, Miller Liam, 3, Johnson 个相互比较,则它们将是唯一的,因为这些内存重用恶作剧不会不会发生。