<p>另一个问题是函数会缓存其中的所有常量。在</p>
<p>因此</p>
<pre><code>def f():
return 1.1
assert f() is f() # or id(f()) == id(f())
</code></pre>
<p>通过查看函数的代码对象,可以找到与函数关联的缓存常量。在</p>
^{pr2}$
<p>元组通常是数字、字符串或元组。因此,正如您总是为<code>var1</code>分配一个文本整数,编译器知道这是不能更改的常量值,因此在函数调用之间缓存该整数对象。在</p>
<p>我在<code>f</code>中使用float的原因是这是唯一一个将缓存float的实例。字符串和整数也可以在其他情况下缓存,例如</p>
<pre><code>>>> x = 1.1
>>> y = 1.1
>>> x is y
False
</code></pre>
<p><strong>更新</strong></p>
<p>虽然元组在Python中被认为是不可变的,但在实现级别上,它们只是另一个可变内存。有时,如果Python知道没有其他人可以访问这个tuple,它会对一个tuple进行变异。例如</p>
<pre><code>>>> [id(x) for x in zip("abc", range(3))]
[12684384, 48723328, 12684384] # different tuples
>>> l = []
>>> for x in zip("abc", range(3)):
l.append(id(x))
del x # only the zip iterator has access to yielded tuple now
>>> l
[12684384, 12684384, 12684384]
</code></pre>
<p>请参阅定义zip <a href="https://hg.python.org/cpython/file/3.4/Python/bltinmodule.c#l2290" rel="nofollow">next method</a>的相应行。在</p>
<pre><code>if (Py_REFCNT(result) == 1) { // if we are the only ref holder
Py_INCREF(result);
for (i=0 ; i < tuplesize ; i++) {
it = PyTuple_GET_ITEM(lz->ittuple, i);
item = (*Py_TYPE(it)->tp_iternext)(it);
if (item == NULL) {
Py_DECREF(result);
return NULL;
}
olditem = PyTuple_GET_ITEM(result, i);
PyTuple_SET_ITEM(result, i, item); // modify in place
Py_DECREF(olditem);
}
</code></pre>