“名称变量”和“存储变量”之间是否存在差异?

时间:2013-04-27 08:44:55

标签: python variables

我已经听到并且随处读到变量是Python中的“名称而不是存储”,并且重要的是不要将它们视为存储,但我没有找到一个为什么重要的例子。所以问题是,为什么区分变量名称和变量是存储的重要性呢?

3 个答案:

答案 0 :(得分:6)

a = SomeObject()
b = a

如果名称是存储(例如,它们在C和C ++中),则ab实际上每个都包含一个对象:

a +---------+
  | value 1 |
  +---------+

b +---------+
  | value 2 |
  +---------+

因此,例如,a.x = ...将对值1进行操作,而值2则完全不受影响。请注意,那些提供值的语言允许操纵一个值(例如指针)。但是,这与本主题无关,您可以在Python的模型中执行类似的操作。

在Python和类似语言中,内存看起来更像是这样:

a +-------------+
  | reference 1 | ---------+
  +-------------+          v
                      +---------+
                      | value 1 |
                      +---------+
b +-------------+          ^
  | reference 2 | ---------+
  +-------------+

这里引用的是一个虚构的标记,它引用(duh!)对象。对任何对象都可以有任意数量的引用,对象不知道它们中的任何对象,如果没有对它的引用,对象仍然可以徘徊。另请注意,变量不是弹出引用的唯一位置 - 列表包含引用,dicts包含引用,对象的属性包含引用等。它有点像C中的指针,除了它不是可辨别的值,更不用说语言中的对象(因此也没有与指针算术等价的对象)。

最明显的结果是变量可以是别名,因此通过另一个变量可以看到value #1到一个变异:

a.something = 1
b.something = 2
assert a.something == 2

重新赋值变量是而不是变量值1,它只是改变了引用。换句话说,a = ...不会影响b,反之亦然!

答案 1 :(得分:1)

与C不同,变量“包含”数据 在Python中,名称是对数据存储位置的引用。

所以,列表(可变)

>>> x = [10]
>>> y = x
>>> id(x) == id(y) # they refer to the same object
True
>>> y.append(1) # manipulate y
>>> x # x is manipulated
[10, 1]
>>> y # and so is y.
[10, 1]

并使用字符串(不可变)

>>> x = '10'
>>> y = x
>>> id(x) == id(y)
True
>>> y += '1' # manipulate y
>>> id(x) == id(y) # the ids are no longer equal
False
>>> x # x != y
'10'
>>> y
'101'

当你del变量时,你删除了对象的引用,当一个对象有0个引用时,它被垃圾收集。

答案 2 :(得分:0)

这种东西通常用绘图框和箭头来解释:

C:

pos = { .x = 1, .y = 2 }

-------            -----------
| pos |----------->| x:1 y:2 |
-------            -----------

pos2 = pos 

-------            -----------
| pos |----------->| x:1 y:2 |
-------            -----------

-------            -----------
| pos2|----------->| x:1 y:2 |
-------            -----------

pos2.x = 9

-------            -----------
| pos |----------->| x:1 y:2 |
-------            -----------

-------            -----------
| pos2|----------->| x:9 y:2 |
-------            -----------

的Python:

pos = { 'x':1, 'y': 2 }

-------            -----------        -----------
| pos |----------->| 0xabcde |------->| x:1 y:2 |
-------            -----------        -----------

pos2 = pos                       

-------            -----------  
| pos |----------->| 0xabcde |--\
-------            -----------  |     -----------
                                |---->| x:1 y:2 |
-------            -----------  |     -----------
| pos2|----------->| 0xabcde |--/ 
-------            -----------  

pos2.x = 9                       

-------            -----------  
| pos |----------->| 0xabcde |--\
-------            -----------  |     -----------
                                |---->| x:9 y:2 |
-------            -----------  |     -----------
| pos2|----------->| 0xabcde |--/ 
-------            -----------  

也就是说,python变量本质上是指针。它们不包含“值”,而是包含值的地址。将一个变量分配给另一个变量时,只复制地址。当您更改变量时,实际上是在更改其基础值。

@ delnan的绘画更好(?)但他们错过了一个重点:

python中的

变量不是抽象的“名称”。它们确实有值,这些值不是神秘的“引用”,它们几乎是具体的内存地址。每次访问变量都涉及双重间接:首先我们获取变量的值(这是一个地址),其次,我们看看谁“生活”在这个地址上。

请注意,python在这方面并不是唯一的,其他“脚本”语言使用类似的机制。