====== 第二章:变量与数据类型 ====== ===== 本章目标 ===== 完成本章学习后,你将能够: * 理解变量的本质和Python的变量模型 * 掌握Python的所有基本数据类型 * 理解可变对象与不可变对象的区别 * 掌握类型转换和类型检查 * 理解Python的内存管理机制 ===== 变量基础 ===== ==== 什么是变量 ==== 在编程中,**变量**是用于存储数据的命名位置。可以将变量看作是一个贴有标签的盒子,盒子里装着数据。 # 变量赋值 name = "Alice" age = 25 pi = 3.14159 ==== Python的变量模型 ==== Python的变量与其他语言不同。在Python中: * **变量是指向对象的引用**,而不是存储数据的盒子 * **赋值操作是将名字绑定到对象**,而不是复制数据 # 图解:变量与对象 a = [1, 2, 3] # a指向列表对象 b = a # b也指向同一个列表对象 b.append(4) # 修改列表 print(a) # [1, 2, 3, 4] —— a也变了! 内存示意: 变量a ──→ [1, 2, 3, 4] ←── 变量b ==== 变量命名规则 ==== 1. 只能包含字母、数字、下划线 2. 不能以数字开头 3. 不能是Python关键字 4. 区分大小写 # 合法变量名 name = "Alice" _name = "private" name2 = "Bob" user_name = "Charlie" UserName = "David" # 不同变量 # 非法变量名 2name = "error" # SyntaxError:不能以数字开头 my-name = "error" # SyntaxError:不能包含连字符 my name = "error" # SyntaxError:不能包含空格 class = "error" # SyntaxError:关键字 ==== Python关键字 ==== 以下单词是Python保留的,不能用作变量名: import keyword print(keyword.kwlist) # ['False', 'None', 'True', 'and', 'as', 'assert', 'async', # 'await', 'break', 'class', 'continue', 'def', 'del', # 'elif', 'else', 'except', 'finally', 'for', 'from', # 'global', 'if', 'import', 'in', 'is', 'lambda', # 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', # 'try', 'while', 'with', 'yield'] ===== 基本数据类型 ===== Python有以下基本数据类型: | 类型 | 名称 | 示例 | 说明 | | int | 整数 | 42, -100, 0 | 任意精度整数 | | float | 浮点数 | 3.14, -0.5 | 双精度浮点数 | | bool | 布尔值 | True, False | 逻辑值 | | str | 字符串 | "hello" | 文本数据 | | NoneType | 空值 | None | 表示无值 | ==== 整数(int)==== Python的整数可以**任意精度**,只受限于可用内存。 # 整数定义 a = 42 b = -100 c = 0 # 不同进制 binary = 0b1010 # 二进制,等于10 octal = 0o777 # 八进制,等于511 hexadecimal = 0xFF # 十六进制,等于255 # 大整数(Python自动处理) big_number = 123456789012345678901234567890 print(big_number * big_number) # 不会溢出! # 类型检查 print(type(a)) # ==== 浮点数(float)==== Python的float是**双精度浮点数**(IEEE 754标准,64位)。 # 浮点数定义 pi = 3.14159 negative = -0.5 scientific = 1.5e-3 # 科学计数法,等于0.0015 # 浮点数精度问题 print(0.1 + 0.2) # 0.30000000000000004,不是精确的0.3! # 解决方案:使用decimal模块 from decimal import Decimal a = Decimal('0.1') b = Decimal('0.2') print(a + b) # 0.3,精确计算 # 无穷大和NaN inf = float('inf') neg_inf = float('-inf') not_a_number = float('nan') ==== 布尔值(bool)==== 布尔类型只有两个值:**True** 和 **False**。 # 布尔值 flag = True empty = False # 布尔运算 print(True and False) # False print(True or False) # True print(not True) # False # 比较运算产生布尔值 print(5 > 3) # True print(5 == 3) # False # 类型实际上是int的子类 print(isinstance(True, int)) # True print(True + True) # 2(True等于1) print(False * 10) # 0(False等于0) ==== 空值(None)==== **None** 表示 absence of a value(无值)。 # None表示没有值 result = None # 函数默认返回值 def do_nothing(): pass print(do_nothing()) # None # 检查是否为None if result is None: print("还没有结果") # 注意:不要用 == 检查None,要用 is print(result == None) # True,但不推荐 print(result is None) # True,推荐方式 ===== 类型检查与转换 ===== ==== type()函数 ==== # 检查变量类型 print(type(42)) # print(type(3.14)) # print(type("hello")) # print(type(True)) # print(type(None)) # ==== isinstance()函数 ==== # 检查是否为特定类型 print(isinstance(42, int)) # True print(isinstance(3.14, (int, float))) # True,检查多个类型 # isinstance vs type class Animal: pass class Dog(Animal): pass dog = Dog() print(type(dog) == Animal) # False print(isinstance(dog, Animal)) # True,考虑继承 ==== 类型转换 ==== # 转换为整数 print(int(3.14)) # 3,截断小数部分 print(int("42")) # 42 print(int("1010", 2)) # 10,二进制转十进制 print(int(3.9)) # 3,不是四舍五入! # 转换为浮点数 print(float(42)) # 42.0 print(float("3.14")) # 3.14 # 转换为字符串 print(str(42)) # "42" print(str(3.14)) # "3.14" print(str(True)) # "True" print(str([1, 2, 3])) # "[1, 2, 3]" # 转换为布尔值 print(bool(1)) # True print(bool(0)) # False print(bool("hello")) # True,非空字符串 print(bool("")) # False,空字符串 print(bool([1, 2])) # True,非空列表 print(bool([])) # False,空列表 ===== 可变对象与不可变对象 ===== 这是Python中**最重要的概念之一**。 ==== 不可变对象(Immutable)==== 创建后不能被修改的对象: * int(整数) * float(浮点数) * bool(布尔值) * str(字符串) * tuple(元组) * frozenset(冻结集合) # 整数不可变 a = 5 print(id(a)) # 140735890123456 a = a + 1 # 创建新对象 print(id(a)) # 140735890123488,不同的地址! # 字符串不可变 s = "hello" # s[0] = "H" # TypeError: 'str' object does not support item assignment s = "H" + s[1:] # 创建新字符串 print(s) # "Hello" ==== 可变对象(Mutable)==== 创建后可以修改的对象: * list(列表) * dict(字典) * set(集合) * 自定义类的实例(默认) # 列表可变 lst = [1, 2, 3] print(id(lst)) # 4334567890 lst.append(4) # 修改原对象 print(id(lst)) # 4334567890,相同地址! print(lst) # [1, 2, 3, 4] lst[0] = 100 # 修改元素 print(lst) # [100, 2, 3, 4] ==== 深浅拷贝 ==== 由于可变对象的特性,有时需要创建副本: import copy # 浅拷贝 original = [1, [2, 3], 4] shallow = original.copy() # 或 list(original) 或 original[:] original[0] = 100 print(shallow[0]) # 1,不变 original[1][0] = 200 print(shallow[1]) # [200, 3],变了!因为内部列表是共享的 # 深拷贝 deep = copy.deepcopy(original) original[1][1] = 300 print(deep[1]) # [200, 3],不变 ===== Python内存管理 ===== ==== 引用计数 ==== Python使用**引用计数**来管理内存: import sys a = [1, 2, 3] print(sys.getrefcount(a)) # 2(a的引用 + getrefcount的参数引用) b = a print(sys.getrefcount(a)) # 3 del b print(sys.getrefcount(a)) # 2 当对象的引用计数降为0时,内存会被回收。 ==== 垃圾回收 ==== 对于循环引用,Python使用**垃圾回收器(GC)**: import gc # 手动运行垃圾回收 gc.collect() # 查看垃圾回收统计 print(gc.get_stats()) # 禁用/启用垃圾回收 gc.disable() # ... 做一些性能敏感的操作 ... gc.enable() ==== 小整数缓存 ==== Python缓存了小整数(-5到256): a = 100 b = 100 print(a is b) # True,同一个对象 c = 1000 d = 1000 print(c is d) # False(在某些Python实现中可能是True) ==== 字符串驻留 ==== Python会**驻留**(intern)一些字符串: a = "hello" b = "hello" print(a is b) # True c = "hello world!" d = "hello world!" print(c is d) # False,长字符串不一定驻留 # 手动驻留 e = sys.intern("hello world!") f = sys.intern("hello world!") print(e is f) # True ===== 变量作用域 ===== ==== LEGB规则 ==== Python按以下顺序查找变量: * **L**ocal —— 局部作用域 * **E**nclosing —— 嵌套函数的外层函数作用域 * **G**lobal —— 全局作用域 * **B**uilt-in —— 内置作用域 # 示例 x = "global" # G def outer(): x = "enclosing" # E def inner(): x = "local" # L print(x) # 输出 "local" inner() print(x) # 输出 "enclosing" outer() print(x) # 输出 "global" ==== global和nonlocal ==== count = 0 def increment(): global count # 声明使用全局变量 count += 1 increment() print(count) # 1 def outer(): value = 10 def inner(): nonlocal value # 使用外层函数的变量 value = 20 inner() print(value) # 20 outer() ===== 本章练习 ===== 1. **类型检测器**:编写程序接收用户输入,判断并输出其数据类型 2. **温度转换器**:编写程序在摄氏、华氏、开尔文温度之间转换 3. **内存探秘**:使用id()函数验证可变与不可变对象的行为差异 4. **深浅拷贝实验**:创建一个包含多层嵌套的列表,验证深浅拷贝的区别 5. **变量交换**:不使用临时变量,交换两个变量的值 ===== 本章小结 ===== 本章我们深入学习了: * Python的变量模型(引用语义) * 基本数据类型及其特性 * 类型检查与转换 * 可变对象与不可变对象的区别(关键概念!) * Python内存管理机制 * 变量作用域规则 理解可变与不可变对象是掌握Python的关键,这将帮助你避免许多常见的编程错误。 下一章:[[python_course:chapter03|第三章:运算符与表达式]]