欢迎光临
我们一直在努力

python 数据容器

🐍 Python 新手必看:数据容器完全指南(列表、元组、字符串、字典、集合与通用操作)

程序离不开数据,而数据容器就是 Python 存放数据的"收纳盒"。学会使用列表、元组、字符串、字典、集合五大基础容器,你就掌握了处理批量数据的核心能力。


一、什么是数据容器?

数据容器就是能同时存放多个数据的对象。

想象你要管理班级成绩:

  • 不用容器:score1 = 85, score2 = 92…(100 个变量,疯了)

  • 用容器:scores = [85, 92, 78, 96, 88](一个变量搞定)

Python 中最常用的基础容器有五类:

容器名称特点符号是否有序
list 列表 可变,可以修改 [ ] ✅ 有序
tuple 元组 不可变,不能修改 ( ) ✅ 有序
str 字符串 文本序列,不可变 ' ' / " " ✅ 有序
dict 字典 键值对存储 {key: value} ❌ 无序(3.7+ 保留插入顺序)
set 集合 不重复,自动去重 { } ❌ 无序

💡 列表、元组、字符串统称为序列(Sequence),因为数据是"排好队"的,可以通过编号访问。字典和集合不是序列。


二、列表(List):最灵活的"收纳盒"

1. 列表的定义

# 空列表
empty = []

# 存同类型数据
scores = [85, 92, 78, 96, 88]

# 存不同类型数据(Python 允许)
info = ["Alice", 20, True, 3.14]

# 嵌套列表(列表里套列表)
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]


2. 列表的常规使用(增删改查)

查:访问元素

fruits = ["苹果", "香蕉", "橙子"]

print(fruits[0]) # 苹果
print(fruits[2]) # 橙子

改:修改元素

fruits[1] = "西瓜"
print(fruits) # ['苹果', '西瓜', '橙子']

增:添加元素

fruits = ["苹果", "香蕉"]

# 末尾追加一个
fruits.append("橙子")
print(fruits) # ['苹果', '香蕉', '橙子']

# 指定位置插入
fruits.insert(1, "草莓") # 在索引1的位置插入
print(fruits) # ['苹果', '草莓', '香蕉', '橙子']

# 合并另一个列表
more = ["葡萄", "芒果"]
fruits.extend(more)
print(fruits) # ['苹果', '草莓', '香蕉', '橙子', '葡萄', '芒果']

删:删除元素

fruits = ["苹果", "香蕉", "橙子", "香蕉"]

# 按值删除(删第一个匹配的)
fruits.remove("香蕉")
print(fruits) # ['苹果', '橙子', '香蕉']

# 按索引删除
del fruits[0]
print(fruits) # ['橙子', '香蕉']

# 弹出最后一个(并返回它)
last = fruits.pop()
print(last) # 香蕉
print(fruits) # ['橙子']

# 清空列表
fruits.clear()
print(fruits) # []


3. 列表的索引:正向与反向

列表的每个元素都有一个编号(索引),从 0 开始。

fruits = ["苹果", "香蕉", "橙子", "葡萄", "西瓜"]

# 正向索引(从左往右,从0开始)
print(fruits[0]) # 苹果
print(fruits[3]) # 葡萄

# 反向索引(从右往左,从-1开始)
print(fruits[-1]) # 西瓜(最后一个)
print(fruits[-2]) # 葡萄(倒数第二个)

索引示意图:

列表: ["苹果", "香蕉", "橙子", "葡萄", "西瓜"]
正向索引: 0 1 2 3 4
反向索引: -5 -4 -3 -2 -1

⚠️ 注意:索引越界会报错!fruits[10] 会抛出 IndexError。

操作语法返回值注意事项
追加单个 list.append(x) None 加在最后
批量追加 list.extend(iter) None 拆开逐个加
指定插入 list.insert(i, x) None 下标从 0 开始
按下标删 del list[i] 后面元素前移
弹出元素 list.pop(i) 被删元素 默认删最后一个
按值删除 list.remove(x) None 只删第一个,找不到报错
清空 list.clear() None 变成 []
统计次数 list.count(x) 次数(int) 找不到返回 0
查找下标 list.index(x) 下标(int) 找不到报 ValueError
获取长度 len(list) 长度(int) 内置函数

4. 列表的遍历

方法 1:直接遍历元素(最常用)

fruits = ["苹果", "香蕉", "橙子"]

for fruit in fruits:
print(fruit)

方法 2:通过索引遍历(需要修改时用)

for i in range(len(fruits)):
print(f"索引{i}:{fruits[i]}")

方法 3:enumerate()(同时拿索引和元素,推荐)

for i, fruit in enumerate(fruits):
print(f"{i}:{fruit}")

# 还可以从1开始编号
for i, fruit in enumerate(fruits, start=1):
print(f"{i}. {fruit}")


三、元组(Tuple):不可变的"只读列表"

1. 元组的定义

元组和列表很像,唯一的区别是:定义后不能修改。

# 空元组
empty = ()

# 普通元组
info = ("Alice", 20, "北京")

# 单元素元组(注意逗号!)
single = (5,) # ✅ 必须加逗号,否则不是元组
not_tuple = (5) # ❌ 这只是整数 5

# 括号可以省略(但不推荐新手省略)
coordinates = 10, 20 # 等价于 (10, 20)


2. 元组的操作

元组不能增、删、改,只能查:

info = ("Alice", 20, "北京")

# 查:索引访问(和列表一样)
print(info[0]) # Alice
print(info[-1]) # 北京

# 查:遍历(和列表一样)
for item in info:
print(item)

# 查:切片
print(info[0:2]) # ('Alice', 20)

# ❌ 以下都会报错!元组不可变
info[0] = "Bob" # TypeError
info.append("学生") # AttributeError
del info[0] # TypeError


3. 元组 vs 列表

特性列表 []元组 ()
能否修改 ✅ 可以 ❌ 不可以
性能 稍慢 更快
安全性 低(容易被改) 高(数据保护)
使用场景 数据经常变化 数据固定不变

什么时候用元组?

  • 坐标点 (x, y)

  • 数据库记录 ("Alice", 20, "北京")

  • 函数的多个返回值

  • 字典的键(因为键必须不可变)


四、字符串(String):特殊的文本容器

1. 字符串的定义

s1 = 'Hello'
s2 = "Hello"
s3 = '''多行
文本'''

字符串本质上是字符的序列,所以也可以像列表一样索引:

s = "Python"

print(s[0]) # P
print(s[-1]) # n
print(s[1:4]) # yth


2. 字符串的操作

字符串和元组一样,不可变:

s = "Python"

# ✅ 可以查
print(len(s)) # 6
print("th" in s) # True

# ✅ 可以遍历
for char in s:
print(char)

# ❌ 不能改
s[0] = "J" # TypeError!字符串不可变

# 要"修改"只能创建新的
s = "J" + s[1:] # Jython

常用方法:

🔴 字符串一旦创建,就不能被修改!

这意味着字符串没有 append()、insert()、remove() 这类"修改自身"的方法。所有看似"修改"字符串的操作,实际上都是创建并返回一个新的字符串。

Python

复制

s = "hello"
s[0] = "H" # ❌ 报错!TypeError: 'str' object does not support item assignment

记住这一点,你就不会在字符串操作上踩坑了!


三、7 个核心操作详解(附代码演示)

1. 索引取值:字符串[下标]

作用:根据位置(下标)取出字符串中的某个字符。

text = "Python"

print(text[0]) # P (第一个字符,下标从 0 开始)
print(text[1]) # y
print(text[-1]) # n (-1 表示倒数第一个)

💡 小贴士:Python 支持负数索引,-1 是最后一个,-2 是倒数第二个,非常方便!


2. 查找下标:字符串.index(子串)

作用:查找某个子串第一次出现的位置下标。

text = "hello world"

print(text.index("l")) # 2 (第一个 l 在下标 2)
print(text.index("world")) # 6 ("world" 从下标 6 开始)

⚠️ 注意:如果子串不存在,会抛出 ValueError

print(text.index("z")) # ValueError: substring not found

安全用法:先用 in 判

if "z" in text:
print(text.index("z"))


3. 替换内容:字符串.replace(旧串, 新串)

作用:将字符串中所有匹配的"旧串"替换为"新串"。

text = "我喜欢 Python,Python 真棒!"
new_text = text.replace("Python", "Java")

print(new_text) # 我喜欢 Java,Java 真棒!
print(text) # 我喜欢 Python,Python 真棒!(原字符串没变!)

🔴 再次强调:replace() 不会修改原字符串,而是返回一个全新的字符串。原字符串 text 依然保持不变!


4. 分割字符串:字符串.split(分隔符)

作用:按照指定的分隔符,将字符串切成多段,返回一个列表。

text = "苹果,香蕉,葡萄,西瓜"
fruits = text.split(",")

print(fruits) # ['苹果', '香蕉', '葡萄', '西瓜']
print(type(fruits)) # <class 'list'>

💡 常见用法

# 按空格分割
"a b c".split(" ") # ['a', 'b', 'c']

# 不写参数,按任意空白字符分割(空格、制表符、换行等)
"a b \\t c".split() # ['a', 'b', 'c']

⚠️ 同样,原字符串不会被修改!


5. 去除首尾字符:字符串.strip()

作用:移除字符串开头和结尾的指定字符。默认去除空格和换行符。

# 去除首尾空格
text = " hello world "
clean = text.strip()
print(clean) # "hello world"(中间的空格不会被去掉)

# 去除指定字符
url = "www.example.com"
clean = url.strip("w.com") # 去除首尾的 w、.、c、o、m
print(clean) # "example"

💡 小贴士:strip() 非常实用,常用于清理用户输入。比如用户不小心在账号前后多打了空格,用 strip() 就能搞定!

      注:如:要是头尾分别是"rs"和"sr",strip里面的参数填的是"rs",那么这个参数会被拆作两个子串,所以头尾这两个都会被删除,所以strip的参数会被拆作一个一个小子串


6. 统计次数:字符串.count(子串)

作用:统计某个子串在字符串中出现了多少次。

text = "banana"
print(text.count("a")) # 3
print(text.count("na")) # 2
print(text.count("z")) # 0(找不到返回 0,不会报错)

💡 与 index() 不同,count() 在找不到时返回 0,不会报错,用起来更安心。


7. 获取长度:len(字符串)

作用:统计字符串中有多少个字符。

text = "Python"
print(len(text)) # 6

# 中文也是一个字符
text = "你好世界"
print(len(text)) # 4

💡 len() 是 Python 的内置函数,不是字符串的方法,但它对字符串、列表、元组、字典等都适用。


四、方法速查表(建议收藏)

操作语法返回值是否修改原字符串注意事项
索引取值 str[i] 单个字符 ❌ 不修改 下标从 0 开始,支持负数
查找下标 str.index(sub) 下标(int) ❌ 不修改 找不到报 ValueError
替换内容 str.replace(old, new) 新字符串 ❌ 不修改 替换所有匹配项
分割字符串 str.split(sep) 列表(list) ❌ 不修改 默认按空白分割
去除首尾 str.strip(chars) 新字符串 ❌ 不修改 默认去空格和换行
统计次数 str.count(sub) 次数(int) ❌ 不修改 找不到返回 0
获取长度 len(str) 长度(int) ❌ 不修改 内置函数,中文算 1 个字符

五、字典(dict):用"名字"找数据的容器

1. 为什么需要字典?

列表用索引(编号)找数据,但编号没有含义。字典用键(名字)找数据,一目了然。

# 列表:不知道 1 号元素是什么
student_list = ["Alice", 20, "北京"]

# 字典:一眼看懂
student_dict = {
"name": "Alice",
"age": 20,
"city": "北京"
}


2. 字典的定义

# 空字典
empty1 = {}
empty2 = dict()

# 普通字典
student = {
"name": "Alice",
"age": 20,
"city": "北京"
}

# 键可以是数字(但不推荐混用)
scores = {85: "良好", 90: "优秀"}

⚠️ 键的规则:键必须是不可变类型(字符串、数字、元组都可以,列表不行),且同一个字典中键不能重复。


3. 字典的增删改查

查:访问数据

student = {"name": "Alice", "age": 20}

# 方式1:方括号(键不存在会报错!)
print(student["name"]) # Alice
print(student["score"]) # ❌ KeyError!

# 方式2:get() 方法(键不存在返回 None 或默认值,推荐!)
print(student.get("name")) # Alice
print(student.get("score")) # None(不会报错)
print(student.get("score", 0)) # 0(自定义默认值)

改和增:赋值即可

student = {"name": "Alice", "age": 20}

# 修改已有键
student["age"] = 21
print(student) # {'name': 'Alice', 'age': 21}

# 新增键值对(直接赋值)
student["city"] = "北京"
print(student) # {'name': 'Alice', 'age': 21, 'city': '北京'}

删:删除数据

student = {"name": "Alice", "age": 20, "city": "北京"}

# 按键删除
del student["age"]
print(student) # {'name': 'Alice', 'city': '北京'}

# pop():删除并返回该值
city = student.pop("city")
print(city) # 北京
print(student) # {'name': 'Alice'}

# popitem():删除并返回最后一对(Python 3.7+ 按插入顺序)
student.clear() # 清空字典

操作语法作用是否修改原字典Key 不存在时
取值 dict[key] 获取 Value ❌ 不修改 报 KeyError
添加/更新 dict[key] = value 新增或修改 ✅ 修改
弹出删除 dict.pop(key) 删除并返回值 ✅ 修改 报 KeyError
清空 dict.clear() 删除全部 ✅ 修改
获取所有 Key dict.keys() 返回所有键 ❌ 不修改
获取长度 len(dict) 统计键值对数量 ❌ 不修改

4. 字典的遍历

方法 1:遍历键(默认)

student = {"name": "Alice", "age": 20}

for key in student:
print(key)

# 等价于:
for key in student.keys():
print(key)

方法 2:遍历值

for value in student.values():
print(value)

方法 3:遍历键值对(最常用)

for key, value in student.items():
print(f"{key}: {value}")

# 输出:
# name: Alice
# age: 20

💡 items() 返回的是 (键, 值) 元组,可以用解包 key, value 分别接收。


5. 字典的常用方法

student = {"name": "Alice", "age": 20}

# update():合并另一个字典
student.update({"city": "北京", "age": 21})
print(student) # {'name': 'Alice', 'age': 21, 'city': '北京'}

# setdefault():键不存在才设置
student.setdefault("score", 0) # 新增 score=0
student.setdefault("name", "Bob") # name 已存在,不修改

6.字典嵌套

速查表(建议收藏)

操作语法示例说明
访问两层字典 dict["key1"]["key2"] 逐层用中括号
访问字典里的列表 dict["key"][0] 先取字典,再取列表索引
访问列表里的字典 dict["key"][0]["name"] 字典→列表→字典
修改嵌套值 dict["a"]["b"] = 新值 直接赋值即可
向嵌套列表追加 dict["key"].append(x) 先定位到列表
向嵌套字典添加 dict["a"]["新键"] = 值 直接赋值新键
安全访问 dict.get("a", {}).get("b") 避免 KeyError
遍历嵌套 for k, v in dict.items(): 配合多层循环

六、集合(Set):自动去重的"无序袋子"

1. 集合的定义

# 空集合(注意:{} 是空字典!)
empty = set()

# 普通集合
nums = {1, 2, 3, 4, 5}

# 自动去重!重复元素会被忽略
unique = {1, 2, 2, 3, 3, 3}
print(unique) # {1, 2, 3}

⚠️ 集合的元素必须是不可变类型(数字、字符串、元组),不能放列表。


2. 集合的特点

特点说明
无序 没有索引,不能通过 nums[0] 访问
不重复 自动过滤重复元素
可变 可以添加和删除元素

3. 集合的操作

s = {1, 2, 3}

# 增:添加单个元素
s.add(4)
print(s) # {1, 2, 3, 4}

# 增:添加多个元素
s.update([5, 6])
print(s) # {1, 2, 3, 4, 5, 6}

# 删:remove()(元素不存在会报错)
s.remove(3)
print(s) # {1, 2, 4, 5, 6}

# 删:discard()(元素不存在不报错,推荐)
s.discard(100) # 不会报错

# 删:pop()(随机删除一个,因为无序)
item = s.pop()

# 清空
s.clear()

difference() —— 求差集(原集合不变)

作用:返回一个新集合,包含在集合1中,但不在集合2中的元素。原有的两个集合都不会被修改。

set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}

result = set1.difference(set2)
print(result) # {1, 2} (在 set1 里有,set2 里没有的)

print(set1) # {1, 2, 3, 4} —— 没变!
print(set2) # {3, 4, 5, 6} —— 也没变!

通俗理解:set1.difference(set2) 就是"我有,你没有"的元素。


6. difference_update() —— 求差集(修改原集合)

作用:在集合1中,删除那些也在集合2中出现的元素。集合1会被修改,集合2不变。

set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}

set1.difference_update(set2)
print(set1) # {1, 2} —— set1 被修改了!
print(set2) # {3, 4, 5, 6} —— set2 不变

💡 对比记忆:

表格

方法是否修改 set1返回值
difference() ❌ 不修改 返回新集合
difference_update() ✅ 修改 set1 返回 None

7. union() —— 求并集

作用:返回一个新集合,包含两个集合中所有的元素(自动去重)。原有的两个集合都不会被修改。

set1 = {1, 2, 3}
set2 = {3, 4, 5}

result = set1.union(set2)
print(result) # {1, 2, 3, 4, 5} —— 3 只出现一次(去重)

print(set1) # {1, 2, 3} —— 没变
print(set2) # {3, 4, 5} —— 没变

通俗理解:union() 就是"咱俩加起来,重复的只算一次"。

💡 扩展:并集也可以用 | 运算符:set1 | set2,结果一样。


8. len() —— 统计元素个数

作用:获取集合中有多少个元素。

fruits = {"苹果", "香蕉", "葡萄"}
print(len(fruits)) # 3

# 也常用于判断集合是否为空
if len(fruits) == 0:
print("集合是空的")
# 更 Pythonic 的写法:
if not fruits:
print("集合是空的")

💡 len() 是 Python 的内置函数,不是集合的方法,但它对字符串、列表、元组、字典、集合都适用。


三、方法速查表(建议收藏)

操作语法作用是否修改原集合找不到元素时
添加元素 set.add(x) 添加一个元素 ✅ 修改
删除指定 set.remove(x) 删除指定元素 ✅ 修改 报 KeyError
随机取出 set.pop() 随机删除并返回 ✅ 修改 空集合时报错
清空 set.clear() 清空所有元素 ✅ 修改
差集(新) set1.difference(set2) 我有你没有 ❌ 不修改
差集(改) set1.difference_update(set2) 我有你没有,且删掉 ✅ 修改 set1
并集 set1.union(set2) 合并去重 ❌ 不修改
获取长度 len(set) 统计个数 ❌ 不修改

4. 集合的运算(数学集合操作)

集合最强大的功能是集合运算:

a = {1, 2, 3, 4}
b = {3, 4, 5, 6}

# 并集:A 或 B 中的元素(去重)
print(a | b) # {1, 2, 3, 4, 5, 6}

# 交集:A 和 B 共有的元素
print(a & b) # {3, 4}

# 差集:在 A 中但不在 B 中
print(a – b) # {1, 2}

# 对称差集:只在 A 或只在 B 中(去掉共同部分)
print(a ^ b) # {1, 2, 5, 6}


5. 集合的经典应用:去重

nums = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]

# 列表转集合去重,再转回列表
unique_nums = list(set(nums))
print(unique_nums) # [1, 2, 3, 4](顺序可能打乱)


6. 集合的遍历

s = {"苹果", "香蕉", "橙子"}

for fruit in s:
print(fruit)

# 注意:因为无序,每次打印顺序可能不同!


七、序列的共同特征

列表、元组、字符串统称为序列,因为它们具有以下共同特征:

1. 都有索引和切片

# 列表
[1, 2, 3, 4][1:3] # [2, 3]

# 元组
(1, 2, 3, 4)[1:3] # (2, 3)

# 字符串
"1234"[1:3] # "23"

2. 切片语法详

nums = [0, 1, 2, 3, 4, 5]

print(nums[1:4]) # [1, 2, 3] 从1到3
print(nums[:3]) # [0, 1, 2] 从头开始到2
print(nums[3:]) # [3, 4, 5] 从3到末尾
print(nums[:]) # [0,1,2,3,4,5] 复制整个列表
print(nums[::2]) # [0, 2, 4] 每隔一个取一个
print(nums[::-1]) # [5,4,3,2,1,0] 倒序!

3. 都支持 in 和 not in

print(2 in [1, 2, 3]) # True
print(2 in (1, 2, 3)) # True
print("P" in "Python") # True

4. 都支持 + 拼接和 * 重复

# 列表
[1, 2] + [3, 4] # [1, 2, 3, 4]
[1, 2] * 2 # [1, 2, 1, 2]

# 元组
(1, 2) + (3, 4) # (1, 2, 3, 4)

# 字符串
"Py" + "thon" # "Python"
"Ha" * 3 # "HaHaHa"

⚠️ 字典和集合不是序列,所以不支持索引、切片、重复 *!


八、字符串大小比较

字符串可以比较大小,规则是逐字符按 ASCII 码值比较:

print("apple" > "banana") # False
print("abc" > "abb") # True
print("A" > "a") # False(大写字母 ASCII 小于小写)
print("9" > "10") # True(按字符比,'9' > '1')

比较规则详解

"abc" vs "abd"
↓ ↓
'a' == 'a' → 继续
'b' == 'b' → 继续
'c' < 'd' → 结果:"abc" < "abd"

常见字符 ASCII 顺序(从小到大)

print(ord('A')) # 65 (查 ASCII 码)
print(ord('a')) # 97
print(chr(65)) # A (ASCII 码转字符)

💡 记忆口诀:数字 < 大写 < 小写,逐位 PK,决出胜负就停。


九、数据容器的通用操作

以下函数/操作对五大容器大多适用:

1. len():求长度

len([1, 2, 3]) # 3
len((1, 2, 3)) # 3
len("hello") # 5
len({"a": 1, "b": 2}) # 2(键值对的数量)
len({1, 2, 3}) # 3

2. max() / min():最大/最小值

max([3, 1, 4, 2]) # 4
min((3, 1, 4, 2)) # 1
max("abc") # 'c'(按 ASCII 码)

# 字典比较的是键
max({"z": 1, "a": 2}) # 'z'

3. in / not in:成员判断

# 列表、元组、字符串、集合
2 in [1, 2, 3] # True
"a" in ("a", "b") # True
"Py" in "Python" # True
3 in {1, 2, 3} # True

# 字典:判断的是键是否存在
"name" in {"name": "Alice"} # True
"Alice" in {"name": "Alice"}# False(判断的是键,不是值)

4. 类型转换

# 转列表
list("abc") # ['a', 'b', 'c']
list((1, 2, 3)) # [1, 2, 3]
list({"a": 1, "b": 2}) # ['a', 'b'](只保留键)
list({1, 2, 3}) # [1, 2, 3](顺序不定)

# 转元组
tuple([1, 2, 3]) # (1, 2, 3)

# 转字符串
str([1, 2, 3]) # '[1, 2, 3]'(注意:不是"123"!)
"-".join(["a","b"]) # 'a-b'(列表转字符串的正确方式)

# 转集合(自动去重)
set([1, 2, 2, 3]) # {1, 2, 3}

# 转字典(需要键值对序列)
dict([("a", 1), ("b", 2)]) # {'a': 1, 'b': 2}


十、新手避坑指南

❌ 坑 1:列表赋值是引用,不是复制

a = [1, 2, 3]
b = a # b 和 a 指向同一个列表!
b[0] = 999
print(a) # [999, 2, 3] ← a 也被改了!

# ✅ 正确复制方法
b = a.copy() # 或 b = a[:]

❌ 坑 2:元组里的列表可以被修改

t = (1, 2, [3, 4])
t[2].append(5)
print(t) # (1, 2, [3, 4, 5]) ← 元组本身没变,但里面的列表变了!

❌ 坑 3:str() 转列表不会拼接元素

nums = [1, 2, 3]
print(str(nums)) # "[1, 2, 3]"(带括号和逗号)
# 要转成"123":
print("".join(str(x) for x in nums))

❌ 坑 4:索引越界

arr = [1, 2, 3]
print(arr[3]) # ❌ IndexError!最大索引是 2
print(arr[-4]) # ❌ IndexError!最小反向索引是 -3

❌ 坑 5:{} 是空字典,不是空集合

a = {}
print(type(a)) # <class 'dict'> ← 这是字典!

# 空集合必须这样写
b = set()
print(type(b)) # <class 'set'>

❌ 坑 6:字典键不存在用 [] 会报错

d = {"name": "Alice"}
print(d["age"]) # ❌ KeyError!

# ✅ 用 get() 安全访问
print(d.get("age")) # None
print(d.get("age", 0)) # 0

❌ 坑 7:集合元素必须不可变

s = {[1, 2], 3} # ❌ TypeError!列表不能当集合元素
s = {(1, 2), 3} # ✅ 元组可以

❌ 坑 8:字典的键必须不可变

d = {[1, 2]: "a"} # ❌ TypeError!列表不能当键
d = {(1, 2): "a"} # ✅ 元组可以当键
d = {"key": "a"} # ✅ 字符串可以


十一:切片

在 Python 中,切片(Slice) 是一种从序列中"切取"一段子序列的语法。它适用于字符串、列表、元组等所有有序序列。

核心语法只有一行:

序列[起始下标 : 结束下标 : 步长]

通过调整这三个参数,你可以实现:

  • 取前 N 个元素

  • 取后 N 个元素

  • 隔一个取一个

  • 把序列倒过来

  • ……以及各种花式操作


二、三个参数详解

参数作用是否可省略省略时的默认值
起始下标 从哪个位置开始切 ✅ 可以 从头开始(下标 0)
结束下标 切到哪个位置为止 ✅ 可以 切到末尾
步长 每次跳几个元素 ✅ 可以 1(逐个取)

🔴 关键规则:结束下标是不包含的! 也就是"左闭右开"区间 [start, end)。


三、代码实战:从简单到复杂

1. 基础切片:取一段

my_list = [0, 1, 2, 3, 4, 5, 6]

# 取下标 1 到 4(不含 4),即 [1, 2, 3]
print(my_list[1:4]) # [1, 2, 3]

# 从头取到下标 3(不含 3)
print(my_list[:3]) # [0, 1, 2]

# 从下标 3 取到末尾
print(my_list[3:]) # [3, 4, 5, 6]


2. 步长切片:跳着

步长含义示例 [:]
1 一个个取(默认) 01234567
2 每次跳过 1 个 0246
3 每次跳过 2 个 036
N 每次跳过 N-1 个

3. 负步长:反向切片(重点!)

当步长为负数时,表示从后往前取。此时,起始下标和结束下标也要"反向标"。

my_str = "01234567"

# 步长 -1:倒序取全部(经典反转写法!)
result = my_str[::-1]
print(result) # "76543210"

my_list = [0, 1, 2, 3, 4, 5, 6]

# 从下标 3 开始,到下标 1 结束(不含 1),反向步长 -1
result = my_list[3:1:-1]
print(result) # [3, 2]
# 解释:从下标3(值3) → 下标2(值2),下标1(值1)不含,所以停

💡 小贴士:反向切片最容易搞混的就是起始和结束的位置。记住:步长为负时,起始下标要大于结束下标,否则切出来是空的!


4. 反向跳着取

my_tuple = (0, 1, 2, 3, 4, 5, 6)

# 从末尾开始,反向取,步长 -2(每次跳 1 个)
result = my_tuple[::-2]
print(result) # (6, 4, 2, 0)

取元素过程图解:

原序列: 0 1 2 3 4 5 6
下标: 0 1 2 3 4 5 6

[::-2] 从末尾开始,向左每次跳 2 个:
↑ ↑ ↑ ↑
6 4 2 0

结果:(6, 4, 2, 0)


四、切片的通用性

切片语法对字符串、列表、元组完全通用!

# 字符串
s = "abcdef"
print(s[1:4]) # "bcd"

# 列表
lst = [10, 20, 30, 40, 50]
print(lst[1:4]) # [20, 30, 40]

# 元组
t = (10, 20, 30, 40, 50)
print(t[1:4]) # (20, 30, 40)

💡 切片操作不会修改原序列,而是返回一个全新的序列。


五、新手最常犯的 3 个错误

❌ 错误 1:以为切片会修改原序列

lst = [1, 2, 3, 4]
lst[1:3]
print(lst) # 还是 [1, 2, 3, 4]!切片只是"看",不是"改"

✅ 要修改需要重新赋值:

lst = [1, 2, 3, 4]
lst[1:3] = [20, 30] # 这才是修改
print(lst) # [1, 20, 30, 4]

❌ 错误 2:反向切片时起始/结束写反了

lst = [0, 1, 2, 3, 4]
print(lst[1:3:-1]) # [] 空的!因为 1 < 3,但步长是负的,方向反了

✅ 正确做法:反向切片时,起始下标 > 结束下标

print(lst[3:1:-1]) # [3, 2]

❌ 错误 3:忘记"结束下标不含"

s = "hello"
print(s[0:2]) # "he" 不是 "hel"!下标 2 的字符 'l' 是不包含的


六、切片速查表(建议收藏)

需求写法结果示例("abcdef")
取前 3 个 [:3] "abc"
取后 3 个 [-3:] "def"
取中间 2~4 [1:4] "bcd"
去掉首尾各 1 个 [1:-1] "bcde"
隔一个取一个 [::2] "ace"
反转序列 [::-1] "fedcba"
反转后隔一个取 [::-2] "fdb"
复制整个序列 [:] "abcdef"

十二、总结速查表

操作列表 []元组 ()字符串 ""字典 {}集合 {}
可变性 ✅ 可变 ❌ 不可变 ❌ 不可变 ✅ 可变 ✅ 可变
有序性 ✅ 有序 ✅ 有序 ✅ 有序 ✅ 3.7+ ❌ 无序
索引访问 ❌(用键)
切片
遍历
len()
in / not in ✅(查键)
+ 拼接
* 重复
元素唯一性 键唯一 ✅ 唯一
经典用途 通用数据 固定记录 文本处理 键值映射 去重/集合运算

十三、数据容器总结

一、三个分类视角

视角 1:是否支持下标索引?

类型容器说明
序列类型(支持下标) 列表、元组、字符串 元素有固定顺序,可以用 [0]、[1]、[-1] 等方式访问
非序列类型(不支持下标) 集合、字典 元素无序,不能用下标索引。集合靠"值"查找,字典靠"Key"查找

# 序列类型:可以用下标
lst = [10, 20, 30]
print(lst[0]) # 10

s = "hello"
print(s[-1]) # o

# 非序列类型:不能用下标
st = {10, 20, 30}
# print(st[0]) # TypeError!

d = {"a": 1}
# print(d[0]) # KeyError!(字典用 Key 而不是下标)


视角 2:是否支持重复元素?

类型容器说明
支持重复 列表、元组、字符串 相同的值可以出现多次
不支持重复 集合、字典 集合自动去重;字典的 Key 必须唯一

# 支持重复
lst = [1, 1, 2, 2]
print(lst) # [1, 1, 2, 2]

# 不支持重复
st = {1, 1, 2, 2}
print(st) # {1, 2}(自动去重)

d = {"a": 1, "a": 2}
print(d) # {'a': 2}(Key 重复会覆盖)


视角 3:是否可以修改?

类型容器说明
可变(可修改) 列表、集合、字典 创建后可以增删改元素
不可变(不可修改) 元组、字符串 创建后内容固定,任何"修改"操作都会生成新对象

# 可变
lst = [1, 2, 3]
lst.append(4) # ✅ 可以修改

# 不可变
t = (1, 2, 3)
# t[0] = 10 # TypeError!

s = "hello"
# s[0] = "H" # TypeError!
s = s.replace("h", "H") # ✅ 生成新字符串,原字符串没变


二、五大容器特点对比总表

下面这张表,建议收藏或截图保存,写代码时随时查阅:

特性列表 (list)元组 (tuple)字符串 (str)集合 (set)字典 (dict)
元素数量 支持多个 支持多个 支持多个 支持多个 支持多个
元素类型 任意 任意 仅字符 任意 Key-Value 对
Key:除字典外任意不可变类型
Value:任意
下标索引 ✅ 支持 ✅ 支持 ✅ 支持 ❌ 不支持 ❌ 不支持
重复元素 ✅ 支持 ✅ 支持 ✅ 支持 ❌ 不支持 ❌ 不支持(Key唯一)
可修改性 ✅ 可变 ❌ 不可变 ❌ 不可变 ✅ 可变 ✅ 可变
数据有序 ✅ 是 ✅ 是 ✅ 是 ❌ 否 ❌ 否(Python 3.7+ 插入有序)
使用场景 一批数据,可修改、可重复的存储场景 一批数据,不可修改、可重复的存储场景 一串字符的记录场景 一批数据,去重存储场景 一批数据,用 Key 检索 Value 的存储场景

三、一句话选型指南

需求选它
数据需要随时增删改,且允许重复 列表
数据固定不变,只想安全地存储 元组
处理文本字符串 字符串
需要自动去重 集合
需要通过名字(Key)快速查找对应信息 字典

十四、数据容器的通用操作

功能描述
通用 for 循环 遍历容器(字典是遍历 key)
max 容器内最大元素
min() 容器内最小元素
len() 容器元素个数
list() 转换为列表
tuple() 转换为元组
str() 转换为字符串
set() 转换为集合
sorted(序列, [reverse=True]) 排序,reverse=True 表示降序,得到一个排好序的列表
赞(0)
未经允许不得转载:171主机测评 » python 数据容器
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址