使用id()时,[]和list()之间有区别吗?

时间:2016-11-26 17:01:10

标签: python list python-internals

有人可以解释以下内容吗?

为什么id相同,但列表不同?

>>> [] is []
False
>>> id([]) == id([])
True

列表创建有区别吗?

>>> id(list()) == id(list())
False
>>> id([]) == id([])
True

为什么会这样?我得到两个不同的列表。为什么不只有一个,三个或更多?

>>> [].__repr__
<method-wrapper '__repr__' of list object at 0x7fd2be868128>
>>> [].__repr__
<method-wrapper '__repr__' of list object at 0x7fd2be868170>
>>> [].__repr__
<method-wrapper '__repr__' of list object at 0x7fd2be868128>
>>> [].__repr__
<method-wrapper '__repr__' of list object at 0x7fd2be868170>

1 个答案:

答案 0 :(得分:76)

您使用了id()错误。 id([])获取立即丢弃的对象的内存ID 。毕竟,一旦完成id(),就不会再引用任何内容了。因此,下次使用id([])时,Python会看到重新使用内存的机会,而且这些地址确实是相同的。

但是,这是一个实现细节,您不能依赖它,并且它不会始终能够重用内存地址。

请注意,id()值在对象的生命周期中只是唯一的 ,请参阅documentation

  

这是一个整数,在该生命周期内,该对象保证唯一且恒定。 两个生命周期不重叠的对象可能具有相同的id()值。

(大胆强调我的)。

id(list())无法重用内存位置可能是由于推送堆栈上的当前帧调用函数引起的额外堆突变,然后在{{1}时再次弹出它} call return。

list()[]都会生成空列表对象;但您需要先创建对这些单独列表的引用(此处为list()a):

b

使用>>> a, b = [], [] >>> a is b False >>> id(a) == id(b) False >>> a, b = list(), list() >>> a is b False >>> id(a) == id(b) False 时会发生同样的情况。 Python交互式解释器有一个特殊的全局名称[].__repr__,您可以使用它来引用最后生成的结果:

_

这会创建一个额外的引用,因此>>> [].__repr__ <method-wrapper '__repr__' of list object at 0x10e011608> >>> _ <method-wrapper '__repr__' of list object at 0x10e011608> 方法,以及您为其创建的空列表,仍被视为活动。内存位置未释放,不适用于您创建的下一个列表。

但是再次执行__repr__,Python现在将[].__repr__绑定到该新方法对象。突然之前,任何事物都不再引用先前的_方法,并且可以释放它,列表对象也是如此。

第三次执行__repr__时,第一个内存位置再次可用于重用,因此Python就是这样做的:

[].__repr__

您永远不会创建两个以上的列表;前一个(仍由>>> [].__repr__ # create a new method <method-wrapper '__repr__' of list object at 0x10e00cb08> >>> _ # now _ points to the new method <method-wrapper '__repr__' of list object at 0x10e00cb08> >>> [].__repr__ # so the old address can be reused <method-wrapper '__repr__' of list object at 0x10e011608> 引用)和当前的一个。如果要查看更多内存位置,请使用变量添加另一个引用。