数据分析笔记10:数据容器
数据分析笔记10:数据容器
什么是数据容器
数据容器是用于存储数据的结构,不同容器具有不同的特点和用途。
五种主要容器:
| 容器类型 | 符号 | 关键字 | 主要特点 |
|---|---|---|---|
| 列表 | [ ] | list | 可修改、有序、支持索引 |
| 字典 | { } | dict | 键值对、无序、通过键访问 |
| 元组 | ( ) | tuple | 不可修改、有序、支持索引 |
| 字符串 | ' ' 或 " " | str | 字符序列、不可修改 |
| 集合 | set() | set | 无序、不重复元素 |
应用场景
实际应用:爬虫数据存储。 场景:爬取多个网页的数据。
- 创建空列表作为数据容器。
- 爬取第1个网页 → 追加到列表。
- 爬取第2个网页 → 追加到列表。
- 爬取第3个网页 → 追加到列表。
- 所有数据存储在同一个列表中。
- 对列表进行统一处理和分析。
列表
列表的基本概念
定义:列表是用于存储多个数据的有序容器。
特点:
- 使用方括号 [] 表示。
- 可以存储多个数据。
- 支持不同数据类型。
- 数据有顺序(通过索引访问)。
- 可以修改。
基本示例:
li = [2, 2.5, 'world', False]
print(li)
print(type(li)) # 输出:<class 'list'>
列表的核心特性:列表可以一次性存储多个数据,并且这些数据可以是不同的数据类型(整型、浮点型、字符串、布尔型等)。
创建空列表
方法一:直接使用方括号。
li = []
print(li) # 输出:[]
print(type(li)) # 输出:<class 'list'>
方法二:使用list()函数。
li = list()
print(li) # 输出:[]
print(type(li)) # 输出:<class 'list'>
索引
索引规则:
- 索引从0开始。
- 第1个元素索引为0,第2个为1,依此类推。
name_list = ['Alice', 'Bob', 'Charlie']# 索引对应关系:
# Alice → 索引 0
# Bob → 索引 1
# Charlie → 索引 2print(name_list[0]) # 输出:Alice
print(name_list[1]) # 输出:Bob
print(name_list[2]) # 输出:Charlie
索引示意图: 列表:['Alice', 'Bob', 'Charlie']
索引: 0 1 2
切片
基本语法:list[start:stop:step]
参数说明:
- start:起始位置(包含)。
- stop:结束位置(不包含)。
- step:步长(默认为1)。
左闭右开原则:切片遵循左闭右开规则:
- 包含起始索引的元素。
- 不包含结束索引的元素。
例如:list[0:6] 取索引0, 1, 2, 3, 4, 5。
切片示例
name_list = ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace', 'Henry']
# 索引: 0 1 2 3 4 5 6 7
示例1:从开头到指定位置
print(name_list[:6])
# 输出:['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank']
# 从索引0开始,到索引6之前(不包含6)
示例2:从指定位置到结尾
print(name_list[2:])
# 输出:['Charlie', 'David', 'Eve', 'Frank', 'Grace', 'Henry']
# 从索引2开始,一直到最后
示例3:取所有元素
print(name_list[:])
# 输出:['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace', 'Henry']
# 取全部元素
示例4:指定步长
print(name_list[::3])
# 输出:['Alice', 'David', 'Grace']
# 从头到尾,每隔2个取一个(步长为3)
示例5:指定范围和步长
print(name_list[3:7:2])
# 输出:['David', 'Frank']
# 从索引3到7(不含),步长为2
负数索引
负数索引规则:从右向左计数。
- -1 表示最后一个元素。
- -2 表示倒数第二个元素。
- 依此类推。
name_list = ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace', 'Henry']
# 负索引: -8 -7 -6 -5 -4 -3 -2 -1
示例6:到倒数某个元素
print(name_list[:-2])
# 输出:['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank']
# 从开头到倒数第2个之前(不包含倒数第2个)
示例7:负数范围
print(name_list[-5:-2])
# 输出:['David', 'Eve', 'Frank']
# 从倒数第5个到倒数第2个之前
示例8:反向切片
print(name_list[::-1])
# 输出:['Henry', 'Grace', 'Frank', 'Eve', 'David', 'Charlie', 'Bob', 'Alice']
# 反向输出所有元素(步长为-1)
负数步长的注意事项:
当步长为负数时,数据排列方向与步长方向必须一致:
- 步长为正:从左到右。
- 步长为负:从右到左。
如果方向不一致,会返回空列表。
列表常用函数
count() - 统计元素出现次数
name_list = ['Bob', 'Alice', 'Bob']
result = name_list.count('Bob')
print(result) # 输出:2
len() - 获取列表长度
name_list = ['Bob', 'Alice', 'Charlie']
print(len(name_list)) # 输出:3
in - 判断元素是否存在
name_list = ['Bob', 'Alice', 'Charlie']print('Bob' in name_list) # 输出:True
print('David' in name_list) # 输出:False
not in - 判断元素不存在
name_list = ['Bob', 'Alice', 'Charlie']print('David' not in name_list) # 输出:True
print('Bob' not in name_list) # 输出:False
添加元素
append() - 追加单个元素
功能:在列表末尾添加一个元素。
name_list = ['Bob', 'Alice', 'Charlie']
name_list.append('David')
print(name_list)
# 输出:['Bob', 'Alice', 'Charlie', 'David']
追加列表:
name_list = ['Bob', 'Alice', 'Charlie']
name_list.append(['David', 'Eve'])
print(name_list)
# 输出:['Bob', 'Alice', 'Charlie', ['David', 'Eve']]
# 整个列表作为一个元素被添加
extend() - 合并序列
功能:将序列中的每个元素逐一添加到列表。
name_list = ['Bob', 'Alice', 'Charlie']
name_list.extend(['David', 'Eve'])
print(name_list)
# 输出:['Bob', 'Alice', 'Charlie', 'David', 'Eve']
# 列表中的元素被逐一添加
append vs extend:
- append():将整个对象作为一个元素添加;list.append([2, 3]) → 添加一个列表元素。
- extend():将序列拆分,逐一添加元素;list.extend([2, 3]) → 添加两个元素2和3。
extend对字符串的影响:
name_list = ['Bob', 'Alice', 'Charlie']
name_list.extend('David')
print(name_list)
# 输出:['Bob', 'Alice', 'Charlie', 'D', 'a', 'v', 'i', 'd']
# 字符串被拆分成单个字符
insert() - 指定位置插入
功能:在指定索引位置插入元素。
name_list = ['Bob', 'Alice', 'Charlie']
name_list.insert(1, 'David')
print(name_list)
# 输出:['Bob', 'David', 'Alice', 'Charlie']
# 在索引1的位置插入'David',原索引1及之后的元素后移
插入过程示意: 原列表:['Bob', 'Alice', 'Charlie']
索引: 0 1 2
插入后:['Bob', 'David', 'Alice', 'Charlie']
索引: 0 1 2 3
删除元素
del - 删除语句
删除整个列表:
name_list = ['Bob', 'Alice', 'Charlie']
del name_list
print(name_list) # 报错:name_list is not defined
# 整个列表被删除,整个变量不存在
删除指定元素:
name_list = ['Bob', 'Alice', 'Charlie']
del name_list[1] # 删除索引1的元素
print(name_list)
# 输出:['Bob', 'Charlie']
pop() - 删除并返回元素
功能:删除指定索引的元素,并返回被删除的值。
name_list = ['Bob', 'Alice', 'Charlie']
del_name = name_list.pop(1)print(del_name) # 输出:Alice(被删除的元素)
print(name_list) # 输出:['Bob', 'Charlie']
pop()的特殊功能:pop()是唯一能够返回被删除元素的删除方法,在需要记录删除内容的场景中非常有用。
remove() - 删除指定值
功能:删除指定的元素值(不是索引)。
name_list = ['Bob', 'Alice', 'Charlie']
name_list.remove('Alice') # 直接指定要删除的值
print(name_list)
# 输出:['Bob', 'Charlie']
无法获取被删除的值:
name_list = ['Bob', 'Alice', 'Charlie']
del_name = name_list.remove('Alice')
print(del_name) # 输出:None
# remove()不返回被删除的元素
clear() - 清空列表
功能:删除列表中所有元素,保留空列表。
name_list = ['Bob', 'Alice', 'Charlie']
name_list.clear()
print(name_list) # 输出:[]
# 列表变为空,但列表本身还存在
删除方法对比
| 方法 | 删除方式 | 返回值 | 示例 |
|---|---|---|---|
| del | 通过索引 | 无 | del list[1] |
| pop() | 通过索引 | 被删除的元素 | list.pop(1) |
| remove() | 通过元素值 | None | list.remove('Bob') |
| clear() | 清空所有 | None | list.clear() |
修改元素
name_list = ['Bob', 'Alice', 'Charlie']
name_list[0] = 'David' # 修改索引0的元素
print(name_list)
# 输出:['David', 'Alice', 'Charlie']
列表排序与反转
reverse() - 反转列表
name_list = ['Bob', 'Alice', 'Charlie']
name_list.reverse()
print(name_list)
# 输出:['Charlie', 'Alice', 'Bob']
# 倒序排列
sort() - 排序
升序排序(默认):
num_list = [2, 6, 7, 4, 5, 10, 8]
num_list.sort()
print(num_list)
# 输出:[2, 4, 5, 6, 7, 8, 10]
# 从小到大排序
降序排序:
num_list = [2, 6, 7, 4, 5, 10, 8]
num_list.sort(reverse=True)
print(num_list)
# 输出:[10, 8, 7, 6, 5, 4, 2]
# 从大到小排序
循环遍历列表
方法一:直接遍历元素
name_list = ['Bob', 'Alice', 'Charlie']for i in name_list:print(i)# 输出:
# Bob
# Alice
# Charlie
执行逻辑:
- for循环依次从列表中取出每个元素。
- 第1次:i = 'Bob',打印Bob。
- 第2次:i = 'Alice',打印Alice。
- 第3次:i = 'Charlie',打印Charlie。
空列表的处理:
name_list = []for i in name_list:print('Level')
else:print('else')# 输出:else
# 列表为空时,直接执行else
实际应用:搜索功能
name_list = ['Bob', 'Alice', 'Charlie']
name = input('请输入您要搜索的名字:')if name in name_list:print(f'您输入的名字是{name},名字已经存在')
else:print(f'您输入的名字是{name},但不存在')
列表嵌套
嵌套列表结构:
name_list = [['Bob', 'Alice'], ['Charlie', 'David'], ['Eve', 'Frank']]
# 这是一个包含3个子列表的列表
访问嵌套元素:
name_list = [['Bob', 'Alice'], ['Charlie', 'David'], ['Eve', 'Frank']]# 访问第2个子列表
print(name_list[1]) # 输出:['Charlie', 'David']# 访问第2个子列表的第1个元素
print(name_list[1][0]) # 输出:Charlie
多层嵌套:
name_list = [['Bob', ['G', 'H']], ['Charlie', 'David']]# 访问三层嵌套
print(name_list[0][1][0]) # 输出:G
# [0] → ['Bob', ['G', 'H']]
# [1] → ['G', 'H']
# [0] → 'G'
字典
字典的基本概念
定义:字典是以键值对(Key-Value)形式存储数据的容器。
特点:
- 使用大括号 {} 表示。
- 数据以键值对形式存储。
- 与数据顺序无关。
- 通过键(Key)来访问值(Value)。
- 键必须唯一。
基本结构:
dict_1 = {'name': 'Alice','age': 22,'gender': '女'
}
键值对的概念:
键(Key):用于标识数据的标签。
值(Value):键对应的实际数据。
例如:
- 'name': 'Alice' → 键是'name',值是'Alice'。
- 'age': 22 → 键是'age',值是22。
列表 vs 字典
| 特性 | 列表(List) | 字典(Dictionary) |
|---|---|---|
| 符号 | [ ] | { } |
| 数据形式 | 单个元素 | 键值对 |
| 访问方式 | 通过索引(0, 1, 2...) | 通过键(key) |
| 顺序依赖 | 有序 | 无序 |
| 定位方式 | 位置索引 | 键名 |
创建空字典
方法一:直接使用大括号。
dict_1 = {}
print(dict_1) # 输出:{}
print(type(dict_1)) # 输出:<class 'dict'>
方法二:使用dict()函数。
dict_1 = dict()
print(dict_1) # 输出:{}
print(type(dict_1)) # 输出:<class 'dict'>
字典的基本操作
添加元素
dict_1 = {'name': 'Alice', 'age': 22, 'gender': '女'}# 添加新的键值对
dict_1['id'] = 120print(dict_1)
# 输出:{'name': 'Alice', 'age': 22, 'gender': '女', 'id': 120}
删除元素
删除指定键值对:
dict_1 = {'name': 'Alice', 'age': 22, 'gender': '女'}del dict_1['name'] # 删除键为'name'的键值对print(dict_1)
# 输出:{'age': 22, 'gender': '女'}
删除字典元素的规则:只需要删除键(Key)即可,值(Value)会自动跟着被删除。
清空字典:
dict_1 = {'name': 'Alice', 'age': 22, 'gender': '女'}
dict_1.clear()print(dict_1) # 输出:{}
# 字典变为空,但字典本身还存在
修改元素
dict_1 = {'name': 'Alice', 'age': 22, 'gender': '女'}# 修改name的值
dict_1['name'] = 'Bob'print(dict_1)
# 输出:{'name': 'Bob', 'age': 22, 'gender': '女'}
修改过程:
- 通过键名定位要修改的键值对。
- 重新赋值。
- 原值被新值替换。
字典的遍历
遍历键(Keys)
dict_1 = {'name': 'Alice', 'age': 22, 'gender': '女'}for k in dict_1.keys():print(k)# 输出:
# name
# age
# gender
遍历值(Values)
dict_1 = {'name': 'Alice', 'age': 22, 'gender': '女'}for v in dict_1.values():print(v)# 输出:
# Alice
# 22
# 女
遍历键值对(Items)
dict_1 = {'name': 'Alice', 'age': 22, 'gender': '女'}for item in dict_1.items():print(item)# 输出:
# ('name', 'Alice')
# ('age', 22)
# ('gender', '女')
items()的数据结构:
# items()返回的结构类似:
[('name', 'Alice'),('age', 22),('gender', '女')
]
# 列表中每个元素是一个元组
字典方法总结
| 方法 | 功能 | 示例 |
|---|---|---|
| keys() | 获取所有键 | dict.keys() |
| values() | 获取所有值 | dict.values() |
| items() | 获取所有键值对 | dict.items() |
| clear() | 清空字典 | dict.clear() |
元组
元组的基本概念
定义:元组是一种不可修改的数据容器。
特点:
- 使用小括号 () 表示。
- 可以存储多个不同类型的数据。
- 数据不可修改(最重要的特性)。
- 支持索引访问。
- 有序。
tuple_1 = ('BB', 'CC', 'DD', 'EE')
print(tuple_1) # 输出:('BB', 'CC', 'DD', 'EE')
print(type(tuple_1)) # 输出:<class 'tuple'>
元组的不可变性:
一旦元组创建完成,就无法修改其中的数据:
- 不能添加元素。
- 不能删除元素。
- 不能修改元素。
这是元组与列表最大的区别。
尝试修改元组
tuple_1 = ('BB', 'CC', 'DD', 'EE')
tuple_1[0] = 'FF' # 尝试修改第一个元素# 报错:
# TypeError: 'tuple' object does not support item assignment
# 类型错误:元组不支持项目赋值
元组 vs 列表
| 特性 | 列表(List) | 元组(Tuple) |
|---|---|---|
| 符号 | [ ] | ( ) |
| 可修改性 | 可修改 | 不可修改 |
| 索引访问 | 支持 | 支持 |
| 有序性 | 有序 | 有序 |
| 应用场景 | 需要修改的データ | 固定不变的数据 |
元组的优势
数据安全性:
- 防止数据被意外修改。
- 适合存储常量数据。
- 性能比列表稍好。
使用场景:
- 函数返回多个值。
- 不希望数据被修改的场景。
- 作为字典的键(列表不能作为键)。
数据容器对比总结
| 容器 | 符号 | 有序 | 可修改 | 访问方式 | 主要用途 |
|---|---|---|---|---|---|
| 列表 | [ ] | 是 | 是 | 索引 | 通用数据存储 |
| 字典 | { } | 否 | 是 | 键 | 键值对数据 |
| 元组 | ( ) | 是 | 否 | 索引 | 固定数据 |
Python底层原理
为什么变量可以调用方法
name_list = ['Alice', 'Bob', 'Charlie']
name_list.count('Bob') # 为什么变量可以调用count()?
原理解析:
底层模块机制:
- Python内置了list模块,其中定义了各种列表方法。
- 当执行 name_list = [...] 时,变量被赋值为列表类型。
- name_list不再是普通变量,而是一个列表对象。
- 列表对象拥有list模块中的所有方法。
- 通过 . 操作符可以调用这些方法。
同理适用于字典(dict)、元组(tuple)等所有容器类型。
示例:
# 创建列表
li = [2, 3, 4] # li现在是list对象# 创建字典
di = {'b': 2} # di现在是dict对象# 创建元组
tu = (2, 3, 4) # tu现在是tuple对象# 它们都可以调用各自类型的方法
li.append(5) # 调用list的方法
di.keys() # 调用dict的方法
tu.count(2) # 调用tuple的方法
实务应用示例
学生信息管理
# 使用字典存储学生信息
student = {'姓名': '小李','年龄': 20,'数学成绩': 92
}# 添加新信息
student['学号'] = '20230002'# 修改信息
student['数学成绩'] = 88# 查看所有信息
for key, value in student.items():print(f'{key}: {value}')
