我已经听到并且随处读到变量是Python中的“名称而不是存储”,并且重要的是不要将它们视为存储,但我没有找到一个为什么重要的例子。所以问题是,为什么区分变量名称和变量是存储的重要性呢?
答案 0 :(得分:6)
a = SomeObject()
b = a
如果名称是存储(例如,它们在C和C ++中),则a
和b
实际上每个都包含一个对象:
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在这方面并不是唯一的,其他“脚本”语言使用类似的机制。