为什么当[[]是[]“而'{}是{}'返回False时,'()是()'返回True? [英] Why does '() is ()' return True when '[] is []' and '{} is {}' return False?
问题描述
[], {}
或()
实例化对象分别返回了list, dict
或tuple
的新实例;具有新身份的新实例对象.
在我进行实际测试之前,这对我来说很清楚,我注意到() is ()
实际上返回了True
而不是预期的False
:
>>> () is (), [] is [], {} is {}
(True, False, False)
如预期的那样,当使用 list()
, dict()
和<分别分别是href ="https://docs.python.org/3/library/functions.html#func-tuple" rel ="nofollow noreferrer"> tuple()
:
>>> tuple() is tuple(), list() is list(), dict() is dict()
(True, False, False)
[...]例如,
tuple('abc')
返回('a', 'b', 'c')
,而tuple([1, 2, 3])
返回(1, 2, 3)
. 如果未提供任何参数,则构造函数将创建一个新的空元组()
.
这足以回答我的问题.
那么,为什么空元组具有相同的标识,而列表或字典等其他元组却没有呢?
简而言之:
Python内部创建一个元组对象的C
列表,该对象的第一个元素包含空元组.每次使用tuple()
或()
时,Python都会返回上述C
列表中包含的现有对象,而不创建新对象.
对于dict
或list
对象而言,不存在这种机制,相反,这些对象每次都是从头开始重新创建 .
这很可能与以下事实有关:不变的对象(如元组)无法更改,因此保证在执行期间不会更改.考虑到frozenset() is frozenset()
返回True
时,这一点得到进一步巩固.例如()
一个空的frozenset
被视为CPython
的实现.对于可变对象,此类保证没有到位,因此,没有动机来缓存其零元素实例(即,其内容可能会在身份不变的情况下发生变化).
注意: 这不是一个人应该依靠的东西,即一个人不应该将空元组视为单例.在文档中没有明确保证没有此类保证,因此应假定它与实现有关.
如何完成:
在最常见的情况下,CPython
的实现是用两个宏 PyTuple_MAXFREELIST
和 PyTuple_MAXSAVESIZE
设置为正整数.这些宏的正值会导致创建数组tuple
个对象,大小为PyTuple_MAXSAVESIZE
.
使用参数 然后,如果请求一个新的空元组,则位于此列表的第一个位置将被返回,而不是新的实例: 促使这样做的另一个原因是函数调用构造了一个元组来保存将要使用的位置参数.可以在
通过 在同一文件中.如果参数 从本质上讲,这可能是一个经常执行的操作,因此不要每次都构造一个空元组是有意义的. 更多的答案揭示了 From what I've been aware of, using This was pretty clear to me until I actually tested it and I noticed that as expected, this behavior is also manifested when creating objects with The only relevant piece of information I could find in the docs for [...] For example, Suffice to say, this isn't sufficient for answering my question. So, why do empty tuples have the same identity whilst others like lists or dictionaries do not? Python internally creates a Such mechanism does not exist for This is most likely related to the fact that immutable objects (like tuples) cannot be altered and, as such, are guaranteed to not change during execution. This is further solidified when considering that Take note: This isn't something one should depend on, i.e one shouldn't consider empty tuples to be singletons. No such guarantees are explicitly made in the documentation so one should assume it is implementation dependent. In the most common case, the implementation of When Then, if a new empty tuple is requested, the one that is located in the first position of this list is going to get returned instead of a new instance: One additional reason causing an incentive to do this is the fact that function calls construct a tuple to hold the positional arguments that are going to be used. This can be seen in the which is called via In essence, this might be an operation that's performed frequently so it makes sense to not reconstruct an empty tuple every single time. A couple more answers shed light on 这篇关于为什么当[[]是[]“而'{}是{}'返回False时,'()是()'返回True?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!size == 0
调用PyTuple_New
时,请确保 if (size == 0) {
free_list[0] = op;
++numfree[0];
Py_INCREF(op); /* extra INCREF so that this is never freed */
}
if (size == 0 && free_list[0]) {
op = free_list[0];
Py_INCREF(op);
/* rest snipped for brevity.. */
load_args
函数中看到ceval.c
:
static PyObject *
load_args(PyObject ***pp_stack, int na)
{
PyObject *args = PyTuple_New(na);
/* rest snipped for brevity.. */
do_call
调用的na
的数量为零,则将返回一个空的元组.
进一步阅读:
CPython
具有不可变变量的缓存行为:[], {}
or ()
to instantiate objects returns a new instance of list, dict
or tuple
respectively; a new instance object with a new identity. () is ()
actually returns True
instead of the expected False
:>>> () is (), [] is [], {} is {}
(True, False, False)
list()
, dict()
and tuple()
respectively:>>> tuple() is tuple(), list() is list(), dict() is dict()
(True, False, False)
tuple()
states:
tuple('abc')
returns ('a', 'b', 'c')
and tuple([1, 2, 3])
returns (1, 2, 3)
. If no argument is given, the constructor creates a new empty tuple, ()
.In short:
C
list of tuple objects whose first element contains the empty tuple. Every time tuple()
or ()
is used, Python will return the existing object contained in the aforementioned C
list and not create a new one.dict
or list
objects which are, on the contrary, recreated from scratch every time.frozenset() is frozenset()
returns True
; like ()
an empty frozenset
is considered an singleton in the implementation of CPython
. With mutable objects, such guarantees are not in place and, as such, there's no incentive to cache their zero element instances (i.e their contents could change with the identity remaining the same).
How it is done:
CPython
is compiled with two macros PyTuple_MAXFREELIST
and PyTuple_MAXSAVESIZE
set to positive integers. The positive value for these macros results in the creation of an array of tuple
objects with size PyTuple_MAXSAVESIZE
.PyTuple_New
is called with the parameter size == 0
it makes sure to add a new empty tuple to the list if it doesn't already exist:if (size == 0) {
free_list[0] = op;
++numfree[0];
Py_INCREF(op); /* extra INCREF so that this is never freed */
}
if (size == 0 && free_list[0]) {
op = free_list[0];
Py_INCREF(op);
/* rest snipped for brevity.. */
load_args
function in ceval.c
:static PyObject *
load_args(PyObject ***pp_stack, int na)
{
PyObject *args = PyTuple_New(na);
/* rest snipped for brevity.. */
do_call
in the same file. If the number of arguments na
is zero, an empty tuple is going to be returned.
Further reading:
CPython
's caching behaviour with immutables: