第二章:变量与数据类型
本章目标
完成本章学习后,你将能够:
- 理解变量的本质和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)) # <class 'int'>
浮点数(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)) # <class 'int'> print(type(3.14)) # <class 'float'> print(type("hello")) # <class 'str'> print(type(True)) # <class 'bool'> print(type(None)) # <class 'NoneType'>
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按以下顺序查找变量:
- Local —— 局部作用域
- Enclosing —— 嵌套函数的外层函数作用域
- Global —— 全局作用域
- Built-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的关键,这将帮助你避免许多常见的编程错误。
下一章:第三章:运算符与表达式