Python变量分配和`id`关键字

时间:2012-12-20 15:48:49

标签: python parsing variables

  

可能重复:
  Python “is” operator behaves unexpectedly with integers
  Why (0-6) is -6 = False?

所以,在使用id(python 2.6.5)时,我注意到以下内容(shell会话):

>>> a = 1
>>> id(a)
140524904
>>> b = 1
>>> id(b)
140524904

当然,只要修改其中一个变量,就会将其分配给新的内存地址,即

>>> b += 1
>>> id(b)
140524892

最初将具有相同值的变量分配给相同的内存位置或仅仅是CPython的优化是正常的行为吗?

P.S。我花了一点时间浏览parser中的代码,但找不到变量的分配位置和方式。

4 个答案:

答案 0 :(得分:3)

作为mentioned by glglgl,这是CPython的实现细节。如果您在CPython的源代码中查看Objects/longobject.c(例如版本3.3.0),您将找到正在发生的事情的答案:

#if NSMALLNEGINTS + NSMALLPOSINTS > 0
/* Small integers are preallocated in this array so that they
   can be shared.
   The integers that are preallocated are those in the range
   -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/
static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

这解释了为什么在a = 1; b = 1之后,a is bTrue,即使您说a += 2; b +=2; a -= 2; b -= 2。只要计算出一个数字,使其具有适合此数组的值,就可以从该数组中选择生成的对象,从而节省一点内存。

您可以使用如下函数计算出此small_ints数组的范围:

def binary_search(predicate, lo, hi):
    while lo + 1 < hi:
        mid = (lo + hi) / 2
        if predicate(mid):
            lo = mid
        else:
            hi = mid
    return lo

def is_small_int(n):
    p = n + 1
    q = n + 1
    return (p - 1) is (q - 1)

def min_neg_small_int():
    p, q = -1, -1
    if p is not q:
        return 0
    while p is q:
        p += p
        q += q
    return binary_search(is_small_int, p / 2, p) - 1

def max_pos_small_int():
    p, q = 1, 1
    if p is not q:
        return 0
    while p is q:
        p += p
        q += q
    return binary_search(is_small_int, p / 2, p)

def small_int_bounds():
    return (min_neg_small_int(), max_pos_small_int())

对于我的构建(Python 2.7,64位Windows构建),small_int_bounds() == (-5, 256)。这意味着-5256(包括)之间的数字通过small_ints中的Objects/longobject.c数组共享。

-edit-我看到elssar noted有一个similar answer about interning of some literals。正如in the documentation for PyInt_FromLong所述,this answer也提到了这一事实。

答案 1 :(得分:2)

  1. 在python中,所有变量都是指向某些对象的指针。偶数。
  2. Number是不可变对象。因此,CPython不需要创建具有相同值的新对象。
  3. 这并不意味着CPython将始终使用相同的对象。
  4. 在您的第一个示例中,变量ab指向同一个对象。
  5. 当您创建b += 1时,您“创建”新对象2

答案 2 :(得分:2)

这里的术语&#34;变量&#34;必须精确:一方面有对象,另一方面有绑定对象的名称。

如果您执行a = b = 1,则ab都绑定到代表1的同一对象。

如果你做a = 1; b = 1,我认为这是一个CPython细节,它是相同的。通常,实现可以选择两个对象都表示1并在此处使用它们。但由于这会浪费内存,通常不会以这种方式完成。

答案 3 :(得分:1)

ab都引用内存中的同一对象(1),ID为140524904。完成b += 1后,您有2,位于其他地方。