Python 的数据类型体系是理解和使用这门语言的基础,其设计兼具简洁性与强大的表达能力。根据其可变性、存储方式和用途,可以将 Python 的内置数据类型进行多维度划分,核心可分为不可变类型和可变类型两大类,并在此之下包含具体的数据类型[ref_3][ref_4]。
### 一、 按核心特性与可变性划分
| 分类 | 数据类型 | 可变性 | 描述与主要特点 |
| :--- | :--- | :--- | :--- |
| **不可变类型** | **数值型** (`int`, `float`, `complex`, `bool`) | 不可变 | 创建后值无法改变。运算会产生新对象。`bool` 是 `int` 的子类[ref_1][ref_2]。 |
| | **字符串** (`str`) | 不可变 | 由 Unicode 字符组成,支持丰富的格式化与操作方法[ref_1][ref_4]。 |
| | **元组** (`tuple`) | 不可变 | 有序序列,元素不可修改,但可包含可变元素。可用作字典的键[ref_1][ref_4]。 |
| **可变类型** | **列表** (`list`) | 可变 | 有序序列,元素可增删改查,使用最广泛的容器之一[ref_1][ref_4]。 |
| | **集合** (`set`) | 可变 | 无序的不重复元素集,支持数学集合运算(并集、交集、差集等)。存在不可变版本 `frozenset`[ref_1][ref_5]。 |
| | **字典** (`dict`) | 可变 | 键值对映射,键必须是不可变类型,值可以是任意类型[ref_1][ref_5]。 |
| **特殊类型** | **NoneType** (`None`) | 不可变 | 表示“无”或“空”的唯一对象,常用于函数无返回值或变量初始占位[ref_4][ref_6]。 |
### 二、 各数据类型详解与操作
#### 2.1 数值型 (Number)
数值型是不可变类型,包含整数、浮点数、复数和布尔值[ref_1][ref_2]。
* **整数 (`int`)**: 可表示任意大小的整数。
* **浮点数 (`float`)**: 用于表示小数,存在精度限制。
* **复数 (`complex`)**: 形式为 `a + bj`,`a` 为实部,`b` 为虚部。
* **布尔 (`bool`)**: 值为 `True` 或 `False`,是 `int` 的子类 (`True == 1`, `False == 0`)。
```python
# 数值类型示例与运算
num_int = 10
num_float = 3.14
num_complex = 2 + 3j
flag = True # bool 类型
print(type(num_int)) # <class 'int'>
print(type(num_float)) # <class 'float'>
print(type(num_complex)) # <class 'complex'>
print(type(flag)) # <class 'bool'>
print(isinstance(flag, int)) # True,因为 bool 是 int 的子类
# 数值运算会产生新的对象
x = 5
print(id(x)) # 假设 id 为 140707436160560
x = x + 1
print(id(x)) # id 已改变,证明是不可变类型
```
#### 2.2 字符串 (String)
字符串是不可变序列,可以使用单引号、双引号或三引号定义,支持索引、切片和多种方法[ref_1][ref_6]。
```python
# 字符串定义与操作
s1 = 'Hello'
s2 = "World"
s3 = '''多行
字符串'''
# 字符串是不可变的
s = "Python"
# s[0] = 'J' # 这行会报错:TypeError
# 常用操作
print(len(s)) # 获取长度: 6
print(s.upper()) # 转为大写: PYTHON
print(s.find('th')) # 查找子串位置: 2
print(s.replace('P', 'J')) # 替换,返回新字符串: Jython
# 格式化(推荐 f-string)
name = "Alice"
age = 25
greeting = f"My name is {name}, I'm {age} years old."
print(greeting) # My name is Alice, I'm 25 years old.
```
#### 2.3 列表 (List) 与元组 (Tuple)
两者都是有序序列,但可变性是本质区别[ref_1][ref_4]。
```python
# 列表:可变序列
my_list = [1, 2, 3, 'a', 'b']
my_list[0] = 99 # 修改元素
my_list.append('c') # 追加元素
my_list.pop(2) # 移除索引为2的元素
print(my_list) # 输出: [99, 2, 'a', 'b', 'c']
# 列表推导式
squares = [x**2 for x in range(5)]
print(squares) # [0, 1, 4, 9, 16]
# 元组:不可变序列
my_tuple = (1, 2, 3, 'x', 'y')
# my_tuple[0] = 99 # 这行会报错:TypeError
# 元组可作为字典的键
coordinate_dict = { (0, 0): 'origin', (1, 2): 'point A'}
print(coordinate_dict[(1, 2)]) # point A
# 单元素元组必须加逗号
single_tuple = (5,) # 这是一个元组
not_tuple = (5) # 这是一个整数
```
#### 2.4 集合 (Set)
集合是无序的、元素唯一的容器,主要用于成员测试和消除重复元素,支持数学集合运算[ref_1][ref_5]。
```python
# 集合定义与操作
set_a = {1, 2, 3, 3, 4} # 自动去重
set_b = {3, 4, 5, 6}
print(set_a) # 输出: {1, 2, 3, 4},顺序可能不同
print(2 in set_a) # 成员测试: True
print(set_a - set_b) # 差集: {1, 2}
print(set_a | set_b) # 并集: {1, 2, 3, 4, 5, 6}
print(set_a & set_b) # 交集: {3, 4}
print(set_a ^ set_b) # 对称差集: {1, 2, 5, 6}
# 集合推导式
unique_chars = {char for char in 'abracadabra'}
print(unique_chars) # 输出: {'a', 'b', 'c', 'd', 'r'}
```
#### 2.5 字典 (Dictionary)
字典是键值对映射,键必须是不可变类型(如字符串、数字、元组),值是任意类型。从 Python 3.7 开始,字典是有序的(插入顺序)[ref_1][ref_5]。
```python
# 字典定义与操作
student = {'name': 'Alice', 'age': 25, 'courses': ['Math', 'Physics']}
# 访问与修改
print(student['name']) # Alice
print(student.get('grade', 'N/A')) # 安全获取,键不存在返回默认值‘N/A‘
student['age'] = 26 # 修改值
student['grade'] = 'A' # 新增键值对
# 遍历
for key, value in student.items():
print(f"{key}: {value}")
# 字典推导式
word_counts = {'apple': 3, 'banana': 5, 'cherry': 2}
inverted = {count: fruit for fruit, count in word_counts.items()} # 注意值重复会被覆盖
print(inverted) # {3: 'apple', 5: 'banana', 2: 'cherry'}
```
### 三、 数据类型转换与判断
Python 提供了内置函数进行类型间的转换和判断[ref_2][ref_4]。
| 函数 | 作用 | 示例 |
| :--- | :--- | :--- |
| `int(x)` | 将 `x` 转换为整数 | `int('10') -> 10`, `int(3.99) -> 3` |
| `float(x)` | 将 `x` 转换为浮点数 | `float(5) -> 5.0` |
| `str(x)` | 将 `x` 转换为字符串 | `str([1,2]) -> "[1, 2]"` |
| `list(x)` | 将可迭代对象 `x` 转换为列表 | `list((1,2)) -> [1, 2]` |
| `tuple(x)` | 将可迭代对象 `x` 转换为元组 | `tuple([1,2]) -> (1, 2)` |
| `set(x)` | 将可迭代对象 `x` 转换为集合 | `set([1,1,2]) -> {1, 2}` |
| `dict(x)` | 创建字典,`x` 需为 `(key, value)` 对序列 | `dict([('a',1), ('b',2)])` |
| `type(obj)` | 返回对象的类型 | `type([1,2]) -> <class 'list'>` |
| `isinstance(obj, class)` | 判断对象是否为类的实例或子类实例 | `isinstance(True, int) -> True` |
```python
# 类型转换示例
num_str = "123"
num_int = int(num_str) # 字符串转整数
print(num_int + 7) # 130
data_list = [1, 2, 3, 2]
data_set = set(data_list) # 列表转集合(去重)
print(data_set) # {1, 2, 3}
# 类型判断
value = 100
if isinstance(value, (int, float)): # 判断是否为int或float类型
print(f"{value} is a number.") # 100 is a number.
```
### 四、 内存管理与可变/不可变类型的应用
理解数据类型的可变性对内存管理和编写正确的程序至关重要[ref_3]。
* **不可变对象**:由于其值不可变,Python 会进行一些内存优化(如小整数缓存、字符串驻留)。函数传递不可变对象时,函数内部对形参的修改不会影响外部实参,因为它们是完全独立的新对象。
* **可变对象**:函数传递可变对象时,传递的是对同一对象的引用。函数内部修改对象内容会影响外部的变量。这在需要函数副作用时很有用,但也容易引入难以察觉的 Bug。
```python
# 可变性在函数参数传递中的影响
def modify_immutable(num):
num += 10
print(f"Inside function (immutable): {id(num)}") # id 改变
def modify_mutable(lst):
lst.append(100)
print(f"Inside function (mutable): {id(lst)}") # id 不变
a = 5
my_list = [1, 2, 3]
print(f"Before call: a={a}, id(a)={id(a)}") # id a
modify_immutable(a)
print(f"After call: a={a}") # a 仍为 5
print(f"\nBefore call: my_list={my_list}, id(my_list)={id(my_list)}") # id list
modify_mutable(my_list)
print(f"After call: my_list={my_list}") # my_list 变为 [1, 2, 3, 100]
```
总结来说,Python 内置了 `int`, `float`, `complex`, `bool`, `str`, `tuple`, `list`, `set`, `dict`, `NoneType` 等核心数据类型。掌握它们的定义、可变性、常用操作以及相互转换,是进行高效 Python 编程和解决复杂问题的基础[ref_1][ref_2][ref_4][ref_5]。在实际编程中,应根据数据的特性和操作需求(如是否需要排序、去重、键值映射、是否要求不变性)来选择最合适的类型。