python基础之变量的基本概念

一、python变量定义和变量的相关属性
通过变量名称指向内存空间当中存储的值(会在内存开辟一块空间存储变量值,并有一个或者多个变量名指向这个变量)
## 变量命名规则,变量先定义后应引用
由字母,数字和下划线组成;不能使用数字和下划线开头;不能为关键字
## 变量的三大特征
id:根据值的内存地址计算出的值(id是唯一的)

# 定义一个变量
a = 10
# 打印变量的id
print(id(a)) # 会得到一个唯一值的值

type:获取变量的类型

b = 10
print(type(b)) # 返回变量的类型

value: 变量的值的本身
## is 和 == 的区别
is: 判断两个变量的身份即id是否相等
==: 判断两个变量的值本身是否相等
注意1:在python当中,当变量指向一个不可变类型时,python会使用先前已经创建的变量的值,因为不可变类型的对象是不能修改的,不必担心变量值的修改影响到其他变量,所以python采用了这种方法节省内存
注意2:python中虽然字符串对象也是不可变对象,但python有个intern机制,简单说就是维护一个字典,这个字典维护已经创建字符串(key)和它的字符串对象的地址(value),每次创建字符串对象都会和这个字典比较,没有就创建,重复了就用指针进行引用就可以了。相当于python对于字符串也是采用了对象池原理
注意3:在python当中存在一个小整数池的概念,python编译器在启动的时候会开盘很多的内存空间来保存一些常用的数字,当对数字进行使用时,会之间到小整数池当中去取,范围为-5到256

a = 1099
b = 1099
a == b  # True 判断两个变量的值本身是否相等
a is b # True 判断两个变量的身份即id是否相等 b变量会使用a的值
# 在函数当中进行定义
def test1():
    a = 10
    return a
def test2():
    a = 10
    return a
a = test1()
b = test2()
c = test2()
print(a is b) # True
print(c is b) # True
# 在函数当中进行定义不可变类型
def create():
    a = ("A", "B")
    return a
def create2():
    a = ("A", "B")
    return a
A = ("A", "B")
D = ("A", "B")
c = create2()
b = create()
d = create2()
print(A is D)  # True
print(A is b)  # True
print(b is c)  # True
print(c is d)  # True

二、python变量的引用
##python当中直接引用和间接引用以及列表循环引用的概念
直接引用:指的是直接将变量值的内存地址赋值给变量名
间接引用:指的是讲变量值的内存地址存在一个字段(列表)中,变量通过一个该字段(列表)的内存地址访问该字段(列表),往后通过字段(列表)中保存的地址访问真正的变量
列表循环引用:在一个列表的元素中,增加一个元素保存列表2的内存地址,对列表2进行引用,在列表2也增加一个元素保存列表1的内存地址,对列表1进行引用

三、python内存的管理之垃圾回收机制
## 引用计数
变量值关联的变量名称的个数,包括直接引用和间接引用,当变量值的直接引用和间接引用的个数为0时,则对变量值为垃圾,编译器会对其进行回收
## 循环引用引发的内存泄漏
当列表存在循环引用时,如果对循环列表的直引用进行删除,此时,将无法对列表当中的值进行访问,但是间接引用还存在,因此无法对其进行回收,所以会导致内存泄漏python基础之变量的基本概念_第1张图片
## 标记清除
1、当内存不足时,会触发标记清除,会对栈空间里面的变量进行扫描对存在变量引用的变量值标记为存活,对其他的内存空间进行回收
2、标记清除分为两个阶段,第一阶段是标记阶段,它会把所有的『活动对象』打上标记,第二阶段是把那些没有标记的对象『非活动对象』进行回收
python基础之变量的基本概念_第2张图片

在上图中,我们把小黑圈视为全局变量,也就是把它作为root object,从小黑圈出发,对象1可直达,那么它将被标记,对象2、3可间接到达也会被标记,而4和5不可达,那么1、2、3就是活动对象,4和5是非活动对象会被它回收
## 分代回收
1、分代回收会将数据的监管分为三个层次 新生代、青春代和老年代 随着层级的下降监督的频率降低,每新生成一个对象都会检查第0代有没有满,如果满了就开始着手进行垃圾回收.创建的对象都会分配在新生代,年轻代链表的总数达到上限时,Python垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到青春代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。同时,分代回收是建立在标记清除技术基础之上。分代回收同样作为Python的辅助垃圾收集技术处理那些容器对象.

四、变量的深拷贝和浅拷贝
## 可变类型和不可变类型
1、不可变类型:当变量名对应的值发生改变时,对应的id也发生改变,则称该数据类型为不可变数据类型(每次赋值时,都会创建一个新的空间,和是否可变无关)
2、可变数据类型:变量名对应的值发生改变时,对应的id没有发生改变,则称该数据类型为可变的数据类型
3、在python当中,将int , float,str设计为一个不可分割的整体,因此为不可变的类型
在对列表和字典进行操作时,改变列表和字典的内容,并不会改变其地址和位置,因此字典和列表为可变的数据类型,在添加值时,value值可以为任意的数据类型,key值只能为不可变的数据类型
## 浅拷贝
将列表当中的第一层的内存地址,不加区分的拷贝到一个新的列表(修改不可变类型时,不会对拷贝的内容进行影响,修改可变类型时,会对拷贝的内容进行影响)

l1 = [1, 2, 3, 4, 5, [6, 7], (1, 4)]
# 进行浅拷贝
l2 = l1.copy()
# 对浅拷贝后的值进行修改
# 修改不可变类型
l2[1] = 100
print(l1)  # [1, 2, 3, 4, 5, [6, 7]]
print(l2)  # [1, 100, 3, 4, 5, [6, 7], (110,)]
# 对可变类型进行修改
l2[-2][0] = 600
print(l1)  # [1, 2, 3, 4, 5, [600, 7], (1, 4)]
print(l2)  # [1, 100, 3, 4, 5, [600, 7], (110,)]

## 深拷贝
将列表当中的第一层的内存地址,加以区分的拷贝到一个新的列表,当拷贝的内容是一个不可变数据类型时,直接拷贝内存地址,当拷贝的是个可变类型时,会对可变类型再进行一次拷贝,创建一个新的内存空间,进行递归式的拷贝

import copy
l1 = [1, 2, 3, 4, 5, [6, 7], (1, 4)]
# 进行浅拷贝
l2 = copy.deepcopy(l1)
# 对浅拷贝后的值进行修改
# 修改不可变类型
l2[1] = 100
print(l1)  # [1, 2, 3, 4, 5, [6, 7]]
print(l2)  # [1, 100, 3, 4, 5, [6, 7], (110,)]
# 对可变类型进行修改
l2[-2][0] = 600
print(l1)  # [1, 2, 3, 4, 5, [6, 7], (1, 4)] 原列表的值不会收到影响
print(l2)  # [1, 100, 3, 4, 5, [600, 7], (110,)]

五、常量
python从语法上没有常量的概念,要使用常量时使用全大写的方式进行变量命名

你可能感兴趣的:(python学习笔记,python)