第六章:AI进阶之------python的变量与赋值语句(二)
系列文章目录
第一章 Python语言基础与应用领域
第二章 Python 开发环境搭建与工具配置(一)
第二章 Python开发环境搭建与工具配置(二)
第三章:Python基本语法规则详解(一)
第三章:Python基本语法规则详解(二)
文章目录
- 系列文章目录
- 四、变量的内存理解
- 4.1 Python 的引用机制
- 4.2 可变对象与不可变对象的引用差异
- 4.3 浅拷贝基础
- 4.4 变量内存理解的易错点
- 五、综合练习与课堂实践
- 5.1 变量定义与赋值练习
- 5.2 内存理解与浅拷贝练习
- 六、课程总结
- 七、常见问题与解答
- 7.1 变量定义相关问题
- 7.2 赋值语句相关问题
- 7.3 内存理解相关问题
- 八、课后练习
四、变量的内存理解
4.1 Python 的引用机制
在 Python 中,变量并不直接存储值,而是存储对值的引用。这种引用机制是理解 Python 内存管理的关键。
示例说明:
# 创建一个整数对象10,并将变量x指向它x = 10# 创建另一个变量y,将其指向x所引用的对象y = x# 检查x和y是否指向同一对象print(x is y) # 输出:Trueprint(id(x) == id(y)) # 输出:True
引用机制的核心概念:
-
每个对象都有唯一的标识(id)、类型(type)和值(value)。
-
变量是对象的引用,存储的是对象的内存地址。
-
当将一个变量赋值给另一个变量时,实际上是复制了引用,两个变量指向同一个对象。
4.2 可变对象与不可变对象的引用差异
Python 中的对象分为可变对象和不可变对象,它们在引用行为上有显著差异。
不可变对象(如整数、浮点数、字符串、元组):
-
一旦创建,其值不能被修改。
-
对不可变对象进行操作时,会创建新的对象。
示例:不可变对象的引用行为
# 不可变对象示例:字符串s1 = "Hello"s2 = s1 # s2引用s1所指向的字符串对象s1 += " World" # 这里实际上创建了新字符串对象"Hello World",并将s1指向它print(s1) # 输出:Hello Worldprint(s2) # 输出:Helloprint(s1 is s2) # 输出:False(s1和s2现在指向不同的对象)
可变对象(如列表、字典、集合):
-
创建后可以修改其内容。
-
对可变对象的操作会直接修改对象本身,而不会创建新对象。
示例:可变对象的引用行为
# 可变对象示例:列表list1 = [1, 2, 3]list2 = list1 # list2引用list1所指向的列表对象list1.append(4) # 直接修改list1所指向的列表对象print(list1) # 输出:[1, 2, 3, 4]print(list2) # 输出:[1, 2, 3, 4]print(list1 is list2) # 输出:True(list1和list2仍然指向同一对象)
4.3 浅拷贝基础
浅拷贝是创建一个新对象,该对象的顶层是新的,但内部元素仍然是对原对象元素的引用。
实现浅拷贝的方式:
-
使用切片操作(仅适用于序列类型,如列表、元组)
-
使用
copy()
方法(适用于列表、字典等) -
使用
copy
模块的copy()
函数
示例 1:列表的浅拷贝
import copy# 原始列表original = [1, 2, [3, 4]]# 创建浅拷贝shallow_copy = copy.copy(original)# 修改原始列表的顶层元素original[0] = 100# 修改原始列表中的嵌套列表original[2].append(5)# 输出结果print("Original:", original) # 输出:Original: [100, 2, [3, 4, 5]]print("Shallow Copy:", shallow_copy) # 输出:Shallow Copy: [1, 2, [3, 4, 5]]
浅拷贝的特点:
-
新对象与原对象的顶层是不同的(内存地址不同)。
-
新对象的内部元素仍然引用原对象的内部元素。
-
对原对象顶层元素的修改不会影响浅拷贝对象。
-
对原对象内部可变元素的修改会影响浅拷贝对象。
4.4 变量内存理解的易错点
错误 1:对可变对象的引用修改
# 错误示例:修改一个变量影响另一个变量list1 = [1, 2, 3]list2 = list1 # list2引用list1的对象list2.append(4) # 这里修改的是list1和list2共同引用的列表对象print(list1) # 输出:[1, 2, 3, 4](原列表被修改)
错误原因:变量list2
和list1
指向同一个列表对象,修改其中一个会影响另一个。
解决方案:如果需要独立的列表副本,使用浅拷贝:
# 正确示例:使用浅拷贝创建独立副本list1 = [1, 2, 3]list2 = list1.copy() # 或list2 = list1[:]list2.append(4)print(list1) # 输出:[1, 2, 3]print(list2) # 输出:[1, 2, 3, 4]
错误 2:浅拷贝的局限性
# 错误示例:浅拷贝无法隔离嵌套的可变对象import copyoriginal = [1, 2, [3, 4]]shallow_copy = copy.copy(original)original[2].append(5) # 修改嵌套列表print(shallow_copy) # 输出:[1, 2, [3, 4, 5]](浅拷贝对象也被影响)
错误原因:浅拷贝只复制了外层列表,内部的列表仍然是引用。
解决方案:对于嵌套结构,使用深拷贝:
# 正确示例:使用深拷贝创建完全独立的副本import copyoriginal = [1, 2, [3, 4]]deep_copy = copy.deepcopy(original)original[2].append(5)print(deep_copy) # 输出:[1, 2, [3, 4]](深拷贝对象不受影响)
错误 3:误解变量赋值与对象创建
# 错误示例:认为变量赋值会创建新对象x = 10y = xx += 5 # 这里实际上是创建了新的整数对象15,并将x指向它print(y) # 输出:10(y仍然指向原来的整数对象10)
错误原因:整数是不可变对象,x += 5
实际上是创建了新对象,并将x
重新指向新对象,而y
仍然指向原对象。
正确理解:变量赋值是引用传递,不可变对象的修改会创建新对象。
五、综合练习与课堂实践
现在,我们将通过几个实践练习来巩固今天所学的知识。请打开 PyCharm,创建一个新的 Python 文件,命名为variables_practice.py
,然后按照以下练习进行操作。
5.1 变量定义与赋值练习
练习 1:变量命名与类型转换
编写一个 Python 程序,实现以下功能:
-
定义一个整数变量
x
,并赋值为 10。 -
定义一个浮点数变量
y
,并赋值为 3.14。 -
定义一个字符串变量
s
,并赋值为 “Hello, World!”。 -
将这三个变量的值分别转换为其他类型,并打印结果。
预期输出:
x as float: 10.0y as int: 3s as list: ['H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!']
练习 2:多重赋值与解包
编写一个 Python 程序,实现以下功能:
-
创建一个包含三个元素的元组
(1, 2, 3)
。 -
使用多重赋值将元组中的值分别赋给变量
a
,b
,c
。 -
交换
a
和b
的值。 -
使用多重赋值和切片操作,将列表
[4, 5, 6, 7, 8]
中的值赋给变量d
,e
,f
,g
,h
。 -
打印所有变量的值。
预期输出:
a: 2b: 1c: 3d: 4e: 5f: 6g: 7h: 8
5.2 内存理解与浅拷贝练习
练习 3:引用与浅拷贝
编写一个 Python 程序,实现以下功能:
-
创建一个列表
original
,包含元素[1, 2, [3, 4]]
。 -
创建另一个列表
ref
,并将其指向original
。 -
创建
original
的浅拷贝shallow
。 -
修改
original
的第一个元素为 100。 -
修改
original
内部列表的第三个元素为 5。 -
打印所有三个列表的值。
预期输出:
original: [100, 2, [3, 4, 5]]
ref: [100, 2, [3, 4, 5]]
shallow: [1, 2, [3, 4, 5]]
练习 4:深拷贝应用
编写一个 Python 程序,实现以下功能:
- 创建一个嵌套字典
original
,结构如下:
{"name": "Alice","age": 30,"hobbies": ["reading", "music"]
}
-
创建
original
的深拷贝deep
。 -
修改
original
的age
值为 31。 -
修改
original
的hobbies
列表,添加 “sports”。 -
打印
original
和deep
的值。
预期输出:
original: {'name': 'Alice', 'age': 31, 'hobbies': ['reading', 'music', 'sports']}
deep: {'name': 'Alice', 'age': 30, 'hobbies': ['reading', 'music']}
六、课程总结
今天的课程中,我们学习了 Python 中的变量与赋值语句,以及它们的内存模型。这些内容是 Python 编程的基础,也是理解 Python 语言特性的关键。
重点回顾:
- 变量的定义:
-
变量是对象的引用,不需要声明类型,赋值即定义。
-
变量命名必须遵循特定规则,避免与内置函数和关键字冲突。
-
Python 是动态类型语言,变量类型由赋值决定,且可以随时改变。
- 赋值语句:
-
基本赋值(=)是最基础的赋值方式。
-
多重赋值允许在一行代码中为多个变量赋值,可用于交换变量值和解包操作。
-
增量赋值(如 +=、-= 等)是简化变量更新的语法糖。
- 变量的内存理解:
-
Python 采用引用机制,变量存储的是对象的内存地址。
-
可变对象(如列表、字典)的赋值会创建引用,修改一个变量会影响其他引用该对象的变量。
-
浅拷贝创建新对象,但内部元素仍引用原对象的内部元素。
课后任务:
-
复习今天所学的内容,确保完全理解变量的定义、赋值语句和内存模型。
-
完成课堂练习中的四个实践任务。
-
预习下一节课的内容:流程控制语句(条件语句和循环语句)。
下一节课中,我们将学习 Python 的流程控制语句,包括条件判断(if-elif-else)和循环结构(for 和 while 循环)。这些内容将帮助我们编写更复杂、更灵活的程序。
如果你在学习过程中遇到任何问题,请随时提问。祝你学习愉快!
七、常见问题与解答
7.1 变量定义相关问题
问题 1:为什么 Python 中不需要声明变量类型?
解答:Python 是动态类型语言,变量的类型由赋给它的值决定,解释器会在运行时自动推断变量的类型。这种设计使 Python 代码更加简洁灵活。
问题 2:变量名是否区分大小写?
解答:是的,Python 是大小写敏感的语言,myVar
和myvar
被视为两个不同的变量。
问题 3:如何查看变量的类型?
解答:可以使用type()
函数查看变量的类型:
x = 10print(type(x)) # 输出:<class 'int'>
7.2 赋值语句相关问题
问题 1:多重赋值的执行顺序是怎样的?
解答:多重赋值是从右到左执行的,右侧表达式会先被计算,然后依次赋给左侧变量:
x, y = y, x # 正确交换x和y的值
问题 2:增量赋值运算符的优先级如何?
解答:增量赋值运算符的优先级低于比较运算符,但高于赋值运算符:
x = 1x += 2 * 3 # 等价于x = x + (2 * 3),结果为7
问题 3:如何交换两个变量的值?
解答:可以使用多重赋值简洁地交换两个变量的值:
x, y = y, x # 交换x和y的值
7.3 内存理解相关问题
问题 1:为什么修改一个变量会影响另一个变量?
解答:如果两个变量指向同一个可变对象(如列表),修改其中一个变量会影响另一个变量,因为它们共享同一对象:
list1 = [1, 2, 3]list2 = list1list2.append(4)print(list1) # 输出:\[1, 2, 3, 4]
问题 2:如何创建一个列表的独立副本?
解答:可以使用列表的copy()
方法或切片操作创建浅拷贝:
list1 = [1, 2, 3]list2 = list1.copy() # 或list2 = list1\[:]
问题 3:浅拷贝和深拷贝有什么区别?
解答:浅拷贝只复制对象的表层结构,而深拷贝会递归复制所有层级的对象:
import copyoriginal = [1, 2, [3, 4]]
shallow = copy.copy(original)
deep = copy.deepcopy(original)original[2].append(5)
print(shallow) # 输出:[1, 2, [3, 4, 5]](浅拷贝受影响)
print(deep) # 输出:[1, 2, [3, 4]](深拷贝不受影响)
八、课后练习
- 变量定义练习:
-
编写一个程序,定义不同类型的变量(整数、浮点数、字符串、列表、字典),并使用
type()
函数打印它们的类型。 -
尝试将变量重新赋值为不同类型,观察类型变化。
- 赋值语句练习:
-
编写一个程序,使用多重赋值交换三个变量的值。
-
编写一个程序,使用增量赋值计算 1 到 100 的和。
- 内存理解练习:
-
编写一个程序,创建一个列表的浅拷贝和深拷贝,修改原列表的嵌套元素,观察两种拷贝的不同结果。
-
编写一个程序,创建一个字典,修改其值,观察引用和拷贝的不同效果。
通过这些练习,你将能够更好地掌握 Python 的变量与赋值语句,为后续的学习打下坚实的基础。如果你在练习过程中遇到任何问题,请随时在评论区留言!