缺少声明语句的情况
在python中,类型是在运行时自动决定的,而不是通过代码声明。这意味着没有必要事先声明变量。
变量、对象和引用
- 变量创建:一个变量,当代码第一次给它赋值时就创建了它。之后的赋值将会改变已创建的变量名的值;
- 变量类型:类型的概念存在于对象而不存在变量名中;
- 变量使用:当当变量出现在表达式中时,它会立马被当前引用的对象所替代,无论这个对象的类型是什么;
总而言之,变量在赋值的时候才被创建,它可以引用任何类型的对象,并且必须在引用之前赋值。
a = 3
# 上面代码完成了以下三个工作
1、创建一个对象来代表3;
2、创建一个变量a,如果它还没有创建的话;
3、将变量与新的对象3相连;
在python中变量到对象之间的关系称为引用,也就是说引用是关系,通过内存中的指针的形式来实现;
- 变量是一个系统表的入口,包含了指向对象的连接;
- 对象是被分配到的一块内存,有足够的空间去表示他们所代表的值;
- 引用是自动形成的变量到对象的指针;
从技术上讲,对象不仅仅有足够的空间表示它的值,还包含了更复杂的结构,每一个对象都有两个标准的头部信息:类型标志符标识这个对象的类型;引用的计数器决定何时收回这个对象;
类型属性对象,而不是变量
在python中,类型属于对象,而不是变量名。事实上python的变量就是在特定的时间引用一个特定的对象;
每一个对象都包含一个头部信息,其中标记了这个对象的类型。
对象的垃圾收集
在python中,每当一个变量名被赋值一个新的对象,如果原来的对象没有被其他的变量名或者对象引用的话,那么之前的那个对象占用的空间就会被收回。这种自动回收对象空间的技术叫做垃圾回收。
垃圾回收功能的实现:它在每个对象中保留了一个计数器,计数器记录当前指向该对象的引用的数目。一旦这个计数器被设置为零,这个对象的内存空间就会被自动回收。
共享引用
a = 3
b = a
上面的代码实际效果就是变量a和b都引用了相同的对象(即相同的内存空间)
这种情况在python中称为共享引用,即多个变量名引用了同一个对象。名字a和b并没有彼此关联;实际上,python中不可能发上两个变量的相互关联,真实情况是两个变量通过它们的引用指向了同一个对象。
a = 3
b = a
a = 'spam'
上面代码中b仍然引用原始的对象;
a = 3
b = a
a = a + 3
给一个变量赋一个新值,并不是替换原始的对象,而是让这个变量去引用完全不同的一个对象。实际的效果就是对一个变量赋值,仅仅会影响那个被赋值的变量。然而当可变的对象以及原位置的改变进入这个场景时,这种情形会有所改变。
共享引用和原位置修改
L1 = [1, 2, 3]
L2 = L1
L1[0] = 4
上面的代码并没有改变L2,但是它的值将发生变化,因为它引用了一个原位置改变对象。
这种行为仅针对支持原位改变的可变对象;
如果不想要这样的现象发生,可以请求python复制对象,而不是创建引用。复制一个列表有两种方法,包括使用list函数或标准库的copy模块。最常用的方法是从头到尾的切片;
L1 = [1, 2, 3]
L2 = L1[:]
L1[0] = 24
这种切片的方法不会使用在其他的核心类型上,复制一个字典或集合应该使用X.copy()方法调用,列表也有这个方法;
import copy
X = copy.copy(Y)
X = copy.deepcopy(Y)