Python3 教程-5. 变量与赋值
变量是编程的地基,极其重要,内容多、细节多,一定要花足够时间反复理解、多写代码练熟。
1. 变量定义与基本赋值
- 变量的本质
- 定义:变量是存储数据的容器,其值可以动态改变,但通常不改变数据类型。Python 中变量无需显式声明,直接赋值即可创建。
- 示例:
1 | age = 25 # 整数类型 |
- 赋值语法
- 基本语法:变量名 = 表达式
- 右侧表达式会被计算后赋值给左侧变量。
- 变量名必须符合标识符规则(字母、下划线开头,区分大小写,非关键字)。
- 基本语法:变量名 = 表达式
- 示例:
1 | x = 10 + 5 # x = 15 |
2. 多变量赋值
- 同时赋相同值
- 语法:
var1 = var2 = ... = value- 右侧表达式先计算,再依次赋值给所有变量。
- 语法:
- 示例:
1 | a = b = c = 10 # a、b、c均为10 |
- 同时赋不同值
- 语法:
var1, var2, ... = val1, val2, ...- 右侧值的数量需与左侧变量一致,顺序对应。
- 语法:
- 示例:
1 | x, y, z = 1, 2.5, "Hello" # x=1, y=2.5, z="Hello" |
- 变量交换
- 技巧:通过多重赋值实现,无需临时变量。
- 示例:
1 | a, b = 10, 20 |
3. 增强赋值语句
- 语法与特性
- 增强赋值符:
+=,-=,*=,/=,=,%=,>>=,<<=,&=,^=,|= - 等价关系:
x += 1等价于x = x + 1,但x仅被求值一次,且可能原地修改对象。
- 增强赋值符:
- 示例:
1 | count = 5 |
- 与普通赋值的区别
- 求值顺序:增强赋值先计算左侧变量(如
a[i] += 1先查找a[i]),而普通赋值先计算右侧。 - 原地操作:对可变对象(如列表)直接修改,而非创建新对象。
- 求值顺序:增强赋值先计算左侧变量(如
4. 变量作用域与类型
- 作用域规则
- 局部变量:在函数内部定义,仅在函数内有效。
- 全局变量:在函数外定义,全局有效。需用
global关键字在函数内修改。
- 示例:
1 | global_var = 100 |
- 动态类型特性
- 类型自动推断:变量类型由赋值决定,可随时改变。
- 示例:
1 | x = 10 # x是整数 |
5. 变量命名规范
- 命名规则(除了遵守标识符规则,还要易懂)
- 允许字符:字母、数字、下划线(
_),首字符不能是数字 - 小写字母 + 下划线(蛇形命名):
user_name、total_price - 见名知意:
age比a好 - 常量一般全大写:
PI = 3.14 - 大驼峰:大驼峰法把第一个单词的首字母也大写了。常用于类名,函数名,属性,命名空间。例如:
StudentInfo - 小驼峰:除第一个单词之外,其他单词首字母大写。例如:myStudentCount
- 禁止使用:关键字(如
if,for)、特殊符号(如@,$)
- 允许字符:字母、数字、下划线(
- 示例:
1 | user_age = 30 # 合法 |
⚠️注意:标识符是统称,变量名只是标识符的一种。
- 标识符 = 所有你自己起的名字
- 包括:变量名、函数名、类名、模块名、方法名
- 只要是程序员自定义的名字,都叫标识符。
- 变量名 = 用来标识变量的标识符
- 所有变量名都是标识符
- 但标识符不一定是变量名(还可以是函数名、类名等)
6. 链式赋值与对象引用
- 链式赋值
- 特性:从右向左依次赋值,修改后续变量不影响前置变量。
- 示例:
1 | a = b = c = 10 |
上述代码解释:
| 第一步 | 执行顺序 | 结果 | |
|---|---|---|---|
| a=b=c=10 | 先把10 赋值给 c再把 10 赋值给 b最后把 10 赋值给a |
a = 10b = 10c = 10 |
这三个变量各自独立,只是一开始值相同 |
| 第二步 | |||
b += 5 |
b += 5 等价于 b = b + 5原来 b = 10所以: b = 10 + 5 = 15 |
b = 15 | 这一步只修改了 b,和 a、c 没关系 |
- 可变对象与不可变对象
- 不可变对象(如整数、字符串):修改值会创建新对象。
- 可变对象(如列表、字典):修改内容不会改变对象标识。
- 示例:
1 | a = [1, 2, 3] |
代码解释:
| a = [1, 2, 3] | 列表是对象,存在内存里,a 只是指向这个列表的标签。 |
|---|---|
| b = a | 不是把列表复制一份给 b, 而是让 b 和 a 指向同一个列表对象。 |
| a.append(4) | 是在原来那个列表里加了一个元素。 因为 a、b 都指着它,所以打印谁都变成 [1,2,3,4]。 |
| ⚠️注意: |
- 数字、字符串:赋值是传值,改一个不影响另一个。
- 表、字典等对象:赋值是传引用(贴标签),改一个,两个都变。
- 如果你想让
b是独立副本、互不影响,可以这样写:
1 | b = a.copy() |
- 使用
b = a.copy()
1 | a = [1, 2, 3] |
- 使用
b = a[:]
1 | a = [1, 2, 3] |
4. 浅拷贝 VS 深拷贝 **浅拷贝:只拷贝第一层,里面嵌套的东西还是共用**(只抄表面一层) **深拷贝:所有层都彻底复制,完全独立,互不影响**(连里面的东西一起全部抄一遍) - **==浅拷贝:==** - 简单说:你有一个盒子,盒子里还装着一个小盒子。 - 浅拷贝 = 只**复制一个新的大盒子** - 但**里面的小盒子还是原来那个**,没有复制 - 所以: - 改大盒子 → 互不影响 - 改里面的小盒子 → **两个都会变** - 示例:
1 | a = [[1,2], 3] |
1 | import copy |
⚠️ 注意:对于列表这类可变对象,a += b 和 a = a + b 效果不一样
1 | # 增强赋值:原地修改原对象 |
7. 进阶应用📚
- 带标注的赋值
- 语法:var: type = value
- 标注变量类型(用于静态检查工具,不影响运行)
- 语法:var: type = value
- 示例:
1 | age: int = 25 |
上述代码解释:
第一行
age: int = 25是什么?age= 变量名: int= 类型提示 / 类型标注= 25= 真正赋值
重点来了:
: int只是一个 “提醒”、一个 “注释”,不是强制规定!
它的意思是:我建议这个变量存整数,大家看代码时注意一下。
==Python 不会管你,不会检查、不会拦着你。==
- 第二行
age = "二十五"为什么不报错?- 因为:Python 是动态类型语言
变量是什么类型,只看你赋什么值,不看你标注什么。 - 你写
age: int→ 只是提醒 - 你赋值
"二十五"→ Python 就把它变成字符串 - Python 根本不会检查你是不是违背了
: int
所以完全不报错。 - 如果还是不理解可以看看这个比喻
你在桌子上贴了个纸条: - 📝 此位置只放苹果(对应
: int) - 然后你把一个梨放上去(对应赋值字符串)
桌子不会报警,也不会把梨扔掉 - Python 就是这张桌子,它只负责放东西,不负责检查纸条。
- 因为:Python 是动态类型语言
- 解包赋值
- 语法:a, * b, c =
a=1,b=,c=5
*变量名专门用来打包剩下所有值,变成列表
- 语法:a, * b, c =
- 示例:
1 | first, *rest = 11, 22, 33, 44, 55 |
上述代码解释:
- 第一行
first, *rest = 11,22,33,44,55first拿走第一个数:11*rest里的*意思是:
把剩下所有的值,全部打包成一个列表,放进 rest
所以:
first = 11rest = [22, 33, 44, 55]- 第二行
print(rest)- 就把这个列表打印出来。
⚠️ 注意:解包的时候数量要匹配。普通解包要求左边变量的数量,和右边序列的元素数量完全一致,不然会报错:
1 | # 错误!左边2个变量,右边3个元素,不匹配 |
⚠️ 注意:不要把赋值和比较搞混。不要在比较的时候用 = ,赋值的 = 和比较的 == 是两个完全不同的运算符:
1 | # 错误!这是赋值,不是比较,会直接报错 |
练习:
第一部分
下列哪些是合法的 Python 变量名?哪些不合法?请说明原因。
user_age2score_namemy-nameif年龄
完成变量的基本定义与赋值:
- 定义一个变量
score,赋值为 90 - 定义一个变量
name,赋值为字符串小明
- 定义一个变量
多变量赋值:不使用临时变量,如何用一行代码交换变量
a和b的值?写出代码。增强赋值语句:写出下面增强赋值语句的等价普通赋值写法。
a += 5等价于:___b *= 2等价于:___c -= 3等价于:___
简单回答:Python 定义变量时,需要提前声明变量的类型吗?为什么?
链式赋值:执行
a = b = c = 10后,变量a、b、c的值分别是多少?以下代码运行会报错,请指出错误原因:
1 | print(x) |
第二部分
思考:如果在
if语句块中定义了一个变量,在语句块外部能不能访问到这个变量?这和你之后要学的函数里的变量有什么不同?增强赋值的隐藏区别:对于列表对象,
a += [3]和a = a + [3]这两种写法完全等价吗?为什么?对象引用问题:执行以下代码后,变量
b的值会变成什么?请解释原因。1
2
3a = b = [1, 2]
a.append(3)
print(b)多变量解包进阶:执行
a, b, *c = 1, 2, 3, 4后,变量c的值是什么?这个特性在后续处理序列数据时非常常用。常见错误调试:以下代码运行会报错,请指出错误类型和原因,并尝试改正。
1 | x = 10 |
- 思考:Python 语法上支持中文变量名吗?实际开发中为什么不推荐使用?
参考答案
第一部分
合法变量名判断
user_age:合法2score:不合法,变量名不能以数字开头_name:合法my-name:不合法,不能包含减号-if:不合法,if是 Python 关键字年龄:语法合法(Python3 支持中文标识符)
变量定义补全
1 | score = 90 |
- 交换变量
1 | a, b = b, a |
增强赋值等价写法
a += 5等价于:a = a + 5b *= 2等价于:b = b * 2c -= 3等价于:c = c - 3
变量类型声明
不需要提前声明类型。Python 是动态类型语言,解释器会在运行时自动根据赋值的内容推断变量的类型。
链式赋值结果
三个变量的值都是
10。错误原因
变量
x还未定义就被使用,会抛出NameError错误。Python 代码是从上到下顺序执行的,必须先定义变量,才能使用它。
第二部分
if 语句块的变量作用域
在 Python 中,
if、for、while这类语句块不会创建新的作用域,所以块内定义的变量,外部可以直接访问。但后续要学的函数会创建独立的局部作用域,函数内定义的变量,外部默认无法访问。
列表的增强赋值区别
不完全等价。
a += [3]是原地修改列表a,不会创建新的对象。a = a + [3]会先创建一个新的列表,再把它赋值给变量a,会改变原变量的引用。这个区别在可变对象(比如列表)中才会体现,不可变对象(比如整数)中两者效果一致。
对象引用的影响
b的值会变成[1, 2, 3]。原因:
a = b = [1,2]是链式赋值,两个变量都指向了同一个列表对象。修改a指向的对象内容,b因为指向同一个对象,所以也会看到变化。解包结果
c的值是[3, 4]。带
*的变量会收集剩余的所有元素,组成一个列表,这是 Python 中处理序列解包的常用特性。错误调试
错误类型:
UnboundLocalError。原因:函数内部对
x进行了赋值,Python 会将x识别为局部变量,导致print(x)时局部变量还未定义。改正:如果要修改全局变量,需要加
global声明:
1 | x = 10 |
中文变量名
语法上是合法的(Python3 支持 Unicode 标识符),但实际开发不推荐。
原因:会降低代码的兼容性、可读性,不同编码环境可能出问题,也不符合通用的开发规范。

