为什么'()is()'在'为'时返回True,'{}是{'是'返回False?
从我已经知道,使用[], {}或()来实例化对象返回一个新的list, dict或tuple实例; 一个具有新身份的新实例对象。 
 这是相当清楚的,直到我真正testing它,我注意到() is ()实际上返回True而不是预期的False : 
 >>> () is (), [] is [], {} is {} (True, False, False) 
 如预期的那样,这种行为在分别使用list() , dict()和tuple()创build对象时也performance出来: 
 >>> tuple() is tuple(), list() is list(), dict() is dict() (True, False, False) 
 我可以在tuple()的文档中find唯一相关的信息: 
[…]例如,
tuple('abc')返回('a', 'b', 'c')和tuple([1, 2, 3])返回(1, 2, 3)。 如果没有参数,构造函数将创build一个新的空元组()。
我只想说,这还不足以回答我的问题。
那么,为什么空元组具有相同的身份,而其他的如列表或字典不是?
简而言之:
  Python在内部创build一个元组对象列表,其第一个元素包含空元组。 每次使用tuple()或() ,Python都会返回上述C列表中包含的现有对象,而不是创build一个新对象。 
  dict或list对象不存在这种机制,相反, 每次从头开始重新创build 。 
 这很可能与不可变对象(如元组)不可更改的事实有关,因此在执行期间保证不会更改。 当考虑到frozenset() is frozenset()返回True时,这是进一步固化;  like ()一个空的frozenset 在CPython的实现中被认为是一个单例 。 对于可变对象, 这样的保证不存在 ,因此,没有动机来caching它们的零元素实例(即,它们的内容可能随着身份保持不变而改变)。 
注意: 这不是应该依赖的东西,也就是说不应该把空元组看作是单身。 在文档中没有明确的这样的保证,所以应该假设它是依赖于实现的。
它是如何完成的:
 在最常见的情况下, CPython的实现是用两个macrosPyTuple_MAXFREELIST和PyTuple_MAXSAVESIZE设置为正整数编译的。 这些macros的正值导致创build一个大小为PyTuple_MAXSAVESIZE 的tuple对象数组 。 
 当PyTuple_New被调用的参数size == 0它确保添加一个新的空元组 ,如果它不存在: 
 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.. */ 
 引起激励的另外一个原因是,函数调用构造一个元组来保存将要使用的位置参数。 这可以在ceval.c的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的个数为零,则返回一个空的元组。 
实质上,这可能是一个经常执行的操作,所以每次不重build一个空元组是很有意义的。
进一步阅读:
 多一些答案揭示了CPython的caching行为与不可变: 
- 对于整数,可以在这里find另一个在源代码中挖掘的答案。
- 对于string, 这里和这里可以find一些答案。