在 Python 3 中,数据类型是编程的基础。Python 的数据类型主要分为两大类:不可变类型(Immutable)和可变类型(Mutable)。理解这两者的区别对于掌握 Python 的内存管理和函数传参至关重要。
以下是 Python 3 基本数据类型的详细解析:
📌 核心分类速览
| 数据类型 | 具体类型 | 可变性 (Mutable?) | 说明 |
|---|---|---|---|
| 数字 (Number) | int, float, complex, bool | ❌ 不可变 | 数学运算的基础 |
| 字符串 (String) | str | ❌ 不可变 | 文本数据 |
| 列表 (List) | list | ✅ 可变 | 有序的元素集合,最常用 |
| 元组 (Tuple) | tuple | ❌ 不可变 | 有序的元素集合,通常用于固定数据 |
| 字典 (Dictionary) | dict | ✅ 可变 | 键值对 (Key-Value) 映射,Python 3.7+ 保持插入顺序 |
| 集合 (Set) | set, frozenset | ✅ 可变 / ❌ 不可变 | 无序且元素唯一的集合 |
1. 数字 (Numbers)
Python 3 中的数字类型主要包括整数、浮点数、复数和布尔值。
int(整数):Python 3 中int的大小没有上限,可以处理任意大的整数(不再有 Python 2 中的long类型)。float(浮点数):带有小数点的数字,底层是 C 语言的双精度浮点数。complex(复数):由实部和虚部组成,虚部用j或J表示(如3 + 4j)。bool(布尔值):True和False(注意首字母必须大写)。在数值运算中,True等价于1,False等价于0。
a = 100 # int
b = 3.14159 # float
c = 2 + 3j # complex
d = True # bool
# Python 3 的 int 可以非常大
big_num = 2 ** 100
print(type(big_num)) # <class 'int'>
# 布尔值的数值特性
print(True + True) # 输出: 22. 字符串 (String, str)
字符串是由单引号 '、双引号 " 或三引号 ''' / """ 包裹的字符序列。字符串是不可变的,不能直接修改其中的某个字符。
s1 = 'Hello'
s2 = "World"
s3 = """这是一个
多行字符串"""
# 1. 索引与切片 (索引从 0 开始,支持负数索引)
text = "Python"
print(text[0]) # 'P'
print(text[-1]) # 'n' (最后一个字符)
print(text[0:4]) # 'Pyth' (切片:包含起始,不包含结束)
print(text[::-1]) # 'nohtyP' (字符串反转)
# 2. 常用方法 (返回新字符串,原字符串不变)
print(text.upper()) # 'PYTHON'
print(text.replace('P', 'J')) # 'Jython'
print("a,b,c".split(',')) # ['a', 'b', 'c'] (转列表)
print("-".join(['a', 'b'])) # 'a-b' (列表转字符串)
# 3. f-string 格式化 (Python 3.6+ 推荐)
name = "Alice"
age = 25
print(f"My name is {name} and I am {age} years old.")3. 列表 (List, list)
列表是可变的有序序列,可以包含不同类型的元素。它是 Python 中最常用的数据结构。
my_list = [1, 2.5, "apple", True]
# 1. 增
my_list.append("banana") # 末尾添加一个元素
my_list.insert(1, "orange") # 在索引 1 处插入
my_list.extend(["grape", "kiwi"]) # 末尾追加多个元素
# 2. 删
my_list.pop() # 移除并返回最后一个元素
my_list.pop(0) # 移除并返回索引 0 的元素
my_list.remove("apple") # 移除第一个匹配的值
del my_list[1:3] # 删除切片范围的元素
# 3. 改
my_list[0] = "new_value" # 直接通过索引修改
# 4. 查
print("apple" in my_list) # 判断元素是否存在 (返回 True/False)
print(my_list.index("banana")) # 获取元素的索引— is a good separator —
4. 元组 (Tuple, tuple)
元组与列表非常相似,但它是不可变的。通常用于存储不应该被修改的数据(如坐标、数据库记录),且作为字典的键时比列表更安全。
# 定义元组
t1 = (1, 2, 3)
t2 = "a", "b", "c" # 括号可以省略
# ⚠️ 注意:定义只有一个元素的元组时,必须加逗号!
single_tuple = (42,) # 如果没有逗号,(42) 会被当成数学运算的括号
# 元组拆包 (Unpacking) - 非常实用的特性
point = (10, 20)
x, y = point
print(f"x={x}, y={y}") # x=10, y=20
# 尝试修改会报错
# t1[0] = 100 # TypeError: 'tuple' object does not support item assignment5. 字典 (Dictionary, dict)
字典是可变的键值对 (Key-Value) 集合。键 (Key) 必须是不可变类型(如字符串、数字、元组),且必须唯一;值 (Value) 可以是任意类型。
(注:从 Python 3.7 开始,字典默认保持元素的插入顺序)
person = {"name": "Bob", "age": 30, "city": "New York"}
# 1. 增 / 改
person["age"] = 31 # 修改已存在的键
person["job"] = "Engineer" # 添加新键值对
# 2. 删
del person["city"] # 删除指定键
job = person.pop("job") # 删除并返回该键的值
# 3. 查 (推荐使用 get,避免 KeyError)
print(person["name"]) # 'Bob'
print(person.get("salary", 0)) # 如果 'salary' 不存在,返回默认值 0
# 4. 遍历字典
for key, value in person.items():
print(f"{key}: {value}")6. 集合 (Set, set)
集合是可变的、无序的、且元素唯一的集合。底层基于哈希表实现,查找速度极快($O(1)$)。常用于去重和数学集合运算。
# 定义集合 (注意:空集合必须用 set(),{} 会创建空字典)
my_set = {1, 2, 3, 3, 2}
print(my_set) # 输出: {1, 2, 3} (自动去重)
# 1. 增删
my_set.add(4)
my_set.remove(1) # 如果元素不存在会报错
my_set.discard(5) # 如果元素不存在不会报错 (更安全)
# 2. 集合运算
set_a = {1, 2, 3, 4}
set_b = {3, 4, 5, 6}
print(set_a & set_b) # 交集: {3, 4}
print(set_a | set_b) # 并集: {1, 2, 3, 4, 5, 6}
print(set_a - set_b) # 差集 (在A中但不在B中): {1, 2}
print(set_a ^ set_b) # 对称差集 (只在A或只在B中): {1, 2, 5, 6}7. 类型判断与转换
类型判断
推荐使用 isinstance() 而不是 type(),因为 isinstance 会考虑继承关系。
x = 10
print(type(x) is int) # True
print(isinstance(x, (int, float))) # True (检查是否属于元组中的任一类型)类型转换
int("123") # 123 (字符串转整数)
float("3.14") # 3.14 (字符串转浮点数)
str(100) # "100" (数字转字符串)
list("hello") # ['h', 'e', 'l', 'l', 'o'] (字符串转列表)
tuple([1, 2]) # (1, 2) (列表转元组)
set([1, 1, 2]) # {1, 2} (列表转集合,顺便去重)💡 核心避坑指南:可变 vs 不可变
在 Python 中,变量只是对象的引用(标签)。
- 不可变对象(如
int,str,tuple):修改它们的值时,实际上是创建了一个新对象,并将变量指向新对象。 - 可变对象(如
list,dict,set):修改它们的值时,是在原内存地址上直接修改。
常见陷阱示例:
# 陷阱 1:列表的浅拷贝与引用
a = [1, 2, 3]
b = a # b 和 a 指向同一个列表对象
b.append(4)
print(a) # 输出: [1, 2, 3, 4] (a 也被改变了!)
# 正确做法:使用切片或 copy 方法进行真正的拷贝
c = a[:] # 或 c = a.copy()
c.append(5)
print(a) # 输出: [1, 2, 3, 4] (a 不受影响)
# 陷阱 2:默认参数使用可变对象
def add_item(item, target_list=[]): # ⚠️ 危险!默认参数在函数定义时只计算一次
target_list.append(item)
return target_list
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] (不是预期的 [2],因为复用了同一个列表)
# 正确做法:默认参数设为 None
def add_item_safe(item, target_list=None):
if target_list is None:
target_list = []
target_list.append(item)
return target_list如果你对某种特定类型(比如列表推导式、字典的高级用法)有进一步的问题,欢迎随时提问!