☰
python基础之变量的基本概念
2026/10/31 1:47:36 网站建设 项目流程

一、变量定义和变量的相关属性

借助变量名称去往内存空间里头存储的值的方向, 会在内存开辟出一块空间存放变量值, 而且存在一个或者多个变量名朝着这个变量指向。

## 变量命名规则,变量先定义后应引用

它是靠字母, 以及数字, 还有下划线共同组合而成;数字开头这种情况是不被允许使用的, 下划线开头同样不行;关键字也绝对不可以是它。

## 变量的三大特征

id:根据值的内存地址计算出的值(id是唯一的)

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

type:获取变量的类型

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

value: 变量的值的本身

## is 和 == 的区别

is: 判断两个变量的身份即id是否相等

==: 判断两个变量的值本身是否相等

注意1: 于其中, 当变量指向一种不可变类型之际, 会运用先前已然创建的变量的值, 鉴于不可变类型的对象是无法被修改的,不用担忧变量值的修改会对其他变量产生影响, 故而采用了此种方式来节省内存。

注意2: 中, 字符串对象属于不可变对象, 存在一个机制, 简要来讲, 它负责维护一个字典, 该字典所维护的内容是, 已创建的字符串(作为key)以及它对应的字符串对象的地址(作为value), 每次在创建字符串对象时, 都会将其与这个字典作比较, 若不存在则创建, 若重复方才使用指针加以引用便可, 这就相当于针对字符串同样运用了对象池原理。

注意3: 当中有个小整数池的概念, 编译器启动时会划开好多内存空间用来存一些常用数字, 对数字使用时, 会直接从小整数池里去拿, 范围是-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

二、变量的引用

##当中直接引用和间接引用以及列表循环引用的概念

直接引用:指的是直接将变量值的内存地址赋值给变量名

是这样一种情况, 存在这么一个字段(列表), 它里面存放着变量值的内存地址,变量, 是借助这个字段(列表)的内存地址去访问它的, 之后, 又凭借字段(列表)里所保存的地址去访问真正的变量, 这就叫做间接引用。

列表存在循环引用情况, 于一个列表的元素里, 添加一个元素用以保存列表2的内存地址, 接着对列表2进行引用, 随后在列表2里同样增加一个元素用来保存列表1的内存地址, 进而对列表1进行引用。

三、内存的管理之垃圾回收机制

## 引用计数

带有关联变量名称数量的变量值, 其中囊括直接引用与之间接引用这两者, 当处于变量值存在着的直接引用兼间接引用的数量呈现为0这种情况时, 那么针对该那般变量值就可判定为垃圾, 编译器会针对它开展回收操作。

## 循环引用引发的内存泄漏

当列表之中存在循环引用这种情况的时候, 要是针对循环列表的直接引用去实施删除操作, 在这个时候, 就会出现无法对列表里面的值进行访问的情况, 然而间接引用却是依然存在着的, 基于此所以没办法对其进行回收, 进而就会致使内存 现象的产生。

## 标记清除

1、内存不足之际, 会引发标记清除, 会针对栈空间当中的变量予以扫描, 将存在变量引用的变量值标记作存活, 对其余的内存空间实施回收。

2、标记清除被划分成两个不同阶段, 其中一个阶段是标记阶段, 此阶段会针对所有的『活动对象』施加标记, 另一个阶段是面向那些未曾被标记的对象也就是『非活动对象』开展回收操作。

在上面那幅图里, 我们把那个小黑圈看作全局变量, 也就是将其当作root, 从小黑圈开始出发, 对象1能够直接抵达, 那么它就会被标记, 对象2、3能够间接到达同样会被标记, 而4和5到达不了, 那么1、2、3就是处于活动状态的对象, 4和5是处于非活动状态的对象会被它回收。

## 分代回收

1、分代回收就会把数据的监管划分成三个层次, 分别是新生代、青春代以及老年代 , 随着层级的降低监督的频率会下降 , 每新生成一个对象都会去检查第0代有没有满 , 要是满了就会开始着手开展垃圾回收。创建出来的对象都会被分配在新生代 , 当年轻代链表的总数达到上限的时候 , 垃圾收集机制就会被触发 , 把那些能够被回收的对象回收处理掉 , 而那些不会被回收的对象就会被转移到青春代去 , 按照这样类推 , 老年代中的对象是存活时间最为长久的对象 , 甚至是存活在整个系统的生命周期范围之内。与此同时, 分代回收是以标记清除技术为根基而构建的, 分代回收也是作为辅助垃圾收集的技术去处理那些归类为容器的对象的。

四、变量的深拷贝和浅拷贝

## 可变类型和不可变类型

1、有这样一种数据类型被称作不可变类型, 这是当变量名所对应的值出现改变的时候, 与其相对应的id也同时变动, 如果属于这种情况那就表明该数据类型是不可变数据类型, 每一回进行赋值操作的时候, 都会去创建一个全新的空间, 这与实际上是否可变并没有关联。

2、可变数据类型, 变量名所对应的值要是发生了改变, 然而对应的id却没有变动, 这样的话就称该数据类型是可变的数据类型。

3、在其中, 把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,)]

五、常量

在语法方面不存在常量的这一概念, 当需要运用常量之际, 采用全大写的形式来对变量给予命名。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询