1. python变量的本质
Python和Java中变量的本质不一样. Java在定义变量的时候, 就已经确定了该变量的数据类型且不可改变. Python的变量可以理解为给对象的内存空间地址贴上标签,标签可以贴在任何对象上。
a = 1
a = "abc"
上述代码用python解释就是:将变量a贴在整型对象1内存空间上。当a重新贴到“abc”对象内存空间上时,整型对象1会被垃圾回收。
创建对象之后才会把变量分配给对象
2. 标识(引用)、别名、相等性
2.1 标识(id)或者引用
- 每个对象都有标识(id),类型,值。对象一旦创建,它的标识就不会改变;
- 标识就是对象在内存中的地址;is运算符用来比较两个对象的标识(地址);
- 数据的在内存中的地址就是数据的引用,即等价于引用;
- id()函数用来返回对象的标识的整数表示
- python中列表list,字典dict,集合set都是可变对象。包括自定义的类对象也是可变对象。
a = [1,2,3]
print(id(a)) # 输出a的标识
# result
1481049521736
- 总结:列表、字典、集等保存的是对象的引用(地址),就像第五个例子,列表保存的是整数对象1,2,3的地址,这些地址是可以改变的(当重新给元素赋值时),而列表本身也有一个地址,这个地址是不会改变的,这就是可变对象,它指的是元素可变,地址不变。而str、bytes、array.array等单一类型序列是扁平的,保存的不是引用,而是再连续内存中保存的数据本身(对象)
2.2 别名
两个变量指向同一对象,即引用相等,则两个变量互相为别名
a = 1
b = a
# a 与 b互为别名
2.3 相等性
- 指的是“==”操作符,判断两个变量所指的对象的值(不是地址)是否相等
- 存在这样的情况,两个变量所指的对象的值相等,但标识不同,这时因为内存创建了两个对象,两个对象的值相等,但是地址不等
a = [1,2,3]
b = [1,2,3]
print(a==b) # True
print(a is b) # False
2.4 元组的相对不可变性
元组与多数Python集合(列表, 字典, 集,等待)一样,保存的是对象的引用(地址)。如果引用的元素是可变的,即元组本身不可变,元素依然可变。也就是说,元组的不可变性其实是指的是tuple数据结构的物理内容(即保存的引用)不可变,与引用的对象无关。
#示例1
>>> t1 = (1, 2, [30, 40]) #t1不可变,但是t1[-1]可变。
>>> t2 = (1, 2, [30, 40]) #构建元组t2,它的元素与t1一样。
>>> t1 == t2 #虽然t1和t2是不同的对象,但是二者相等——与预期相符。
True
>>> id(t1[-1]) #查看t1[-1]列表的标识。
1631417819656
>>> t1[-1].append(99) #就地修改t1[-1]列表。
>>> t1
(1, 2, [30, 40, 99])
>>> id(t1[-1]) #t1[-1]的标识没变,只是值变了。
1631417819656
>>> t1 == t2 #现在,t1和t2不相等。
False