2

这种行为让我很困惑:

import code

class foo():
    def __init__(self):
        self.x = 1

    def interact(self):
        v = globals()
        v.update(vars(self))
        code.interact(local=v)

c = foo()
c.interact()

Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23) 
(InteractiveConsole)
>>> id(x)
29082424
>>> id(c.x)
29082424
>>> x
1
>>> c.x
1
>>> x=2
>>> c.x
1

为什么'cx'不像'x'的别名?如果我正确理解 id() 函数,它们都在同一个内存地址。

4

3 回答 3

3

从 -5 到 256 的小整数被缓存在 python 中,即它们id()总是相同的。

文档

当前的实现为 -5 到 256 之间的所有整数保留一个整数对象数组,当您在该范围内创建一个 int 时,您实际上只是取回了对现有对象的引用。

>>> x = 1
>>> y = 1            #same id() here as integer 1 is cached by python.
>>> x is y
True

更新:

如果两个标识符返回相同的id()值,则并不意味着它们可以充当彼此的别名,这完全取决于它们指向的对象的类型。

对于不可变对象,您不能在 python 中创建别名。修改对不可变对象的引用之一将使其指向新对象,而对旧对象的其他引用仍将保持不变。

>>> x = y = 300
>>> x is y        # x and y point to the same object
True
>>> x += 1        # modify x
>>> x             #  x now points to a different object 
301
>>> y             #y still points to the old object
300

可以从它的任何引用修改可变对象,但这些修改必须是就地修改。

>>> x = y = []
>>> x is y
True
>>> x.append(1)   # list.extend is an in-place operation
>>> y.append(2)   # in-place operation 
>>> x
[1, 2]
>>> y             #works fine so far
[1, 2]

>>> x = x + [1]   #not an in-place operation
>>> x
[1, 2, 1]          #assigns a new object to x
>>> y              #y still points to the same old object
[1, 2]
于 2013-06-25T22:12:19.440 回答
2

如果我正确理解 id() 函数,它们都在同一个内存地址。

你没有正确理解它。id返回一个整数,保证以下身份:如果保证id(x) == id(y)x is y(反之亦然)。

因此,id它告诉您变量指向的对象(值),而不是变量本身。

与内存地址的任何关系纯粹是实现细节。Python 与 C 不同,它不假定与底层机器(无论是物理的还是虚拟的)有任何特定的关系。python 中的变量都是不透明的,并且不是语言可访问的(即不是一流的)。

于 2013-06-25T22:13:32.180 回答
2

code.interact只是(有效地)x=c.x为你做了。因此,当您检查它们id的 s 时,它们指向的是完全相同的对象。但是x=2为变量创建一个新的绑定x。它不是别名。据我所知,Python 没有别名。

是的,在 CPythonid(x)中是对象x指向的内存地址。它不是变量本身的内存地址x(毕竟,它只是字典中的一个键)。

于 2013-06-25T22:28:39.940 回答