目录
5. 命名元组(collections.namedtuple)
昨天学习了Python的基本数据类型的字符串和数字类型,今天一起来学习基本数据类型中的容器类型分别为list--列表,tuple--元组,range--对象~
题外话:本文是接着按照第二天Python的基础变量类型之字符串和数字类型中对于Python的基础数据类型分类中的容器类型来构建的,至于官方文档中,没有容器类型这个概念,是将其以序列类型 --- list, tuple, range来介绍的。
小编没有严格按照官方文档的介绍顺序,而是以自己的学习顺序记录的,希望大家可以有所收获,后续也会继续补充其他相关知识点!
一、列表(list)
列表是可变序列,通常用于存放同类项目的集合(其中精确的相似程度将根据应用而变化)。
1. 列表的基本特性
可变序列:内容可修改(增删改),有序存储。
异构性:可存放任意类型对象(但通常建议同类数据)。
动态大小:自动扩容/缩容。
2. 创建列表的四种方式
| 方法 | 示例 | 说明 |
|---|---|---|
字面量 [] | [], [1, 'a', True] | 直接定义 |
构造器 list() | list(), list(range(3)) | 可接受任意可迭代对象 |
| 列表推导式 | [x**2 for x in range(5)] | 高效生成列表 |
| 类型转换 | list('abc') → ['a','b','c'] | 从字符串/元组等转换 |
3. 核心操作
3.1 通用序列操作
索引/切片:
lst[0],lst[1:3],lst[::-1](反转)拼接/重复:
[1,2] + [3]→[1,2,3],['a']*3→['a','a','a']成员检测:
'a' in ['a','b']→True
3.2 可变序列操作
| 方法 | 作用 | 示例 |
|---|---|---|
lst.append(x) | 末尾添加元素 | [1].append(2) → [1,2] |
lst.insert(i,x) | 在索引 i 处插入 x | ['a','c'].insert(1,'b') → ['a','b','c'] |
lst.remove(x) | 删除第一个值为 x 的元素 | [1,2,2].remove(2) → [1,2] |
lst.pop([i]) | 移除并返回索引 i 的元素 | ['a','b'].pop(0) → 'a' |
lst.reverse() | 原地反转列表 | [1,2].reverse() → [2,1] |
lst.clear() | 清空列表 | [1,2].clear() → [] |
4. 排序方法 sort()
lst.sort(key=None, reverse=False)
-
原地排序:直接修改原列表,返回
None。 -
参数:
-
key:排序依据的函数(如key=str.lower)。 -
reverse:是否降序(默认False升序)。
-
-
稳定性:相等元素的相对顺序不变。
-
与
sorted()的区别:new_lst = sorted(lst) # 返回新列表,原列表不变 lst.sort() # 直接修改原列表
示例:
users = [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 20}]
users.sort(key=lambda x: x['age']) # 按年龄升序
5.列表的增删改查
5.1 增加操作
#创建初始列表
fruits = ["apple", "banana", "cherry"]
print("初始列表:", fruits) # 输出: ['apple', 'banana', 'cherry']
5.1.1 末尾添加单个元素
# 末尾添加单个元素
fruits.append("orange")
print("\n添加orange后:", fruits) # ['apple', 'banana', 'cherry', 'orange']
5.1.2 指定位置插入元素
# 指定位置插入元素
fruits.insert(1, "grape")
print("在索引1插入grape后:", fruits) # ['apple', 'grape', 'banana', 'cherry', 'orange']
5.1.3 合并另一个列表
# 合并另一个列表
berries = ["strawberry", "blueberry"]
fruits.extend(berries)
print("合并浆果列表后:", fruits) # ['apple', 'grape', 'banana', 'cherry', 'orange', 'strawberry', 'blueberry']
5.2 删除操作
5.2.1 按值删除元素
# 按值删除元素
fruits.remove("banana")
print("\n删除banana后:", fruits) # ['apple', 'grape', 'cherry', 'orange', 'strawberry', 'blueberry']
5.2.2 按索引删除元素
# 按索引删除元素
removed_item = fruits.pop(2) # 删除索引2的元素
print(f"删除索引2的元素({removed_item})后:", fruits) # 删除索引2的元素(cherry)后: ['apple', 'grape', 'orange', 'strawberry', 'blueberry']
5.2.3 清空列表
# 清空列表
fruits.clear()
print("清空列表后:", fruits) # []
5.2.4 重置列表
# 重置列表
fruits = ["apple", "grape", "orange", "kiwi", "mango", "pear"]
5.3 修改操作
5.3.1 直接通过索引修改
fruits[2] = "peach"
print("\n修改索引2为peach后:", fruits) # ['apple', 'grape', 'peach', 'kiwi', 'mango', 'pear']
5.3.2 批量修改切片区间
fruits[1:3] = ["watermelon", "pineapple"]
print("修改切片[1:3]后:", fruits) # ['apple', 'watermelon', 'pineapple', 'kiwi', 'mango', 'pear']
5.4 查找操作
5.4.1 查找元素索引
# 查找元素索引
print("\n查找元素索引:")
print("watermelon的索引:", fruits.index("watermelon")) # 1
try:
print("cherry的索引:", fruits.index("cherry")) # 不存在会报错
except ValueError:
print("cherry不存在于列表中")
5.4.2 检查元素是否存在
# 检查元素是否存在
print("检查元素是否存在:")
print("mango是否在列表中:", "mango" in fruits) # True
print("banana是否在列表中:", "banana" in fruits) # False
5.4.3 统计元素出现次数
# 统计元素出现次数
fruits.append("apple")
print("\n添加重复apple后:", fruits)
print("apple出现次数:", fruits.count("apple")) # 2
5.4.4 遍历列表元素
# 遍历列表元素
print("\n遍历列表元素:")
for i, fruit in enumerate(fruits):
print(f"索引 {i}: {fruit}")
5.5 其他常用操作
# 列表排序
fruits.sort()
print("\n排序后:", fruits) # ['apple', 'apple', 'kiwi', 'mango', 'pear', 'pineapple', 'watermelon']
# 列表反转
fruits.reverse()
print("反转后:", fruits) # ['watermelon', 'pineapple', 'pear', 'mango', 'kiwi', 'apple', 'apple']
# 复制列表
fruits_copy = fruits.copy()
print("\n复制列表:", fruits_copy)
# 列表长度
print("列表长度:", len(fruits)) # 7
5.6 操作说明表格
| 操作类型 | 方法/操作符 | 说明 | 时间复杂度 |
|---|---|---|---|
| 增加 | append(x) | 末尾添加元素 | O(1) |
insert(i, x) | 指定位置插入 | O(n) | |
extend(iterable) | 合并另一个列表 | O(k) | |
| 删除 | remove(x) | 删除首个匹配元素 | O(n) |
pop(i) | 删除指定位置元素 | O(n) | |
clear() | 清空列表 | O(1) | |
| 修改 | lst[i] = x | 修改指定位置元素 | O(1) |
lst[i:j] = [...] | 修改切片区间 | O(k+n) | |
| 查找 | index(x) | 返回元素索引 | O(n) |
x in lst | 检查元素存在 | O(n) | |
count(x) | 统计元素次数 | O(n) | |
| 其他 | sort() | 排序列表 | O(n log n) |
reverse() | 反转列表 | O(n) | |
copy() | 浅拷贝列表 | O(n) |
二、 元组(tuple)
元组是不可变序列,通常用于储存异构数据的多项集(例如由 enumerate() 内置函数所产生的二元组)。
1. 元组核心特性
-
不可变序列:一旦创建,无法修改元素
-
异构数据存储:适合存储不同类型的数据项
-
可哈希性:可作为字典键或集合元素(因其不可变性)
-
内存优化:比列表更轻量,性能更优
2. 元组创建方式
| 方法 | 示例 | 说明 |
|---|---|---|
| 空元组 | t = () | 必须使用圆括号 |
| 单元素元组 | t = (42,) 或 t = 42, | 必须有逗号 |
| 多元素元组 | t = (1, 2, 3) 或 t = 1, 2, 3 | 圆括号可选 |
| 从可迭代对象 | t = tuple('abc') | 转换为 ('a', 'b', 'c') |
| 从列表 | t = tuple([1, 2, 3]) | 转换为 (1, 2, 3) |
a = 1, 2, 3 # 是元组
b = (40) # 是整数(缺少逗号)
c = (40,) # 是元组
3. 元组操作(不可变序列支持)
通用序列操作(返回新对象):
t = (10, 20, 30, 40, 50)
# 索引访问
print(t[0]) # 10
print(t[-1]) # 50
# 切片操作
print(t[1:4]) # (20, 30, 40)
# 拼接
new_t = t + (60, 70) # (10, 20, 30, 40, 50, 60, 70)
# 重复
print(t * 2) # (10, 20, 30, 40, 50, 10, 20, 30, 40, 50)
# 成员检测
print(30 in t) # True
# 长度/最小值/最大值
print(len(t), min(t), max(t)) # 5 10 50
# 计数和索引
print(t.count(20)) # 1
print(t.index(40)) # 3
不支持的操作(引发TypeError):
t[0] = 100 # 错误!不可修改
t.append(60) # 错误!无append方法
del t[1] # 错误!不可删除元素
4. 元组解包(重要特性)
# 基本解包
point = (3, 4)
x, y = point
print(f"x={x}, y={y}") # x=3, y=4
# 函数返回多值
def get_dimensions():
return 1920, 1080
width, height = get_dimensions()
# 带星号解包
values = (1, 2, 3, 4, 5)
a, b, *c, d = values
print(a, b, c, d) # 1 2 [3, 4] 5
# 交换变量
x, y = 10, 20
y, x = x, y # 交换后 x=20, y=10
4.1 什么是解包?
想象你有一个 装满物品的盒子(元组),解包就是把盒子里的物品一件件取出来,分别放到不同的位置(变量)上。就像拆快递包裹一样!
# 一个装着三个值的元组(盒子)
box = ("苹果", "香蕉", "橙子")
# 解包操作:把三个水果分别放进三个果篮
fruit1, fruit2, fruit3 = box
print(fruit1) # 输出:苹果
print(fruit2) # 输出:香蕉
print(fruit3) # 输出:橙子
4.2 解包的实际应用场景
1. 交换变量值(不用临时变量)
a = 5
b = 10
# 传统方法需要临时变量
temp = a
a = b
b = temp
# 解包方法:一行搞定!
a, b = b, a # 现在 a=10, b=5
2. 函数返回多个值
def 获取用户信息():
return "张三", 30, "工程师" # 返回一个元组
# 解包接收返回值
姓名, 年龄, 职业 = 获取用户信息()
print(f"{姓名}今年{年龄}岁,是一名{职业}")
3. 处理部分数据
# 包含5个元素的元组
数据 = (1, 2, 3, 4, 5)
# 只取首尾,中间用*收集
第一个, *中间部分, 最后一个 = 数据
print(第一个) # 输出:1
print(中间部分) # 输出:[2, 3, 4](变成列表)
print(最后一个) # 输出:5
4. 遍历键值对
成绩单 = {"数学": 90, "语文": 85, "英语": 95}
for 科目, 分数 in 成绩单.items(): # .items()返回(键,值)元组
print(f"{科目}成绩:{分数}分")
4.3 解包的特殊技巧
1. 使用_忽略不需要的值
坐标 = (10, 20, 30)
x, y, _ = 坐标 # 忽略z轴值
print(f"X: {x}, Y: {y}")
2. 嵌套解包(解包中的解包)
学生 = ("张三", (1995, 5, 15), "计算机系")
姓名, (年, 月, 日), 专业 = 学生
print(f"{姓名} {年}年{月}月{日}日出生")
3. 函数参数解包
def 画点(x, y, z):
print(f"在({x},{y},{z})画点")
位置 = (10, 20, 5)
画点(*位置) # 相当于画点(10, 20, 5)
5. 命名元组(collections.namedtuple)
当需要通过名称访问字段时使用:
from collections import namedtuple
# 创建命名元组类型
Person = namedtuple('Person', ['name', 'age', 'job'])
# 实例化
bob = Person(name='Bob', age=30, job='Developer')
# 访问字段
print(bob.name) # 'Bob'
print(bob[0]) # 'Bob'(仍支持索引)
print(bob._asdict()) # {'name': 'Bob', 'age': 30, 'job': 'Developer'}
# 创建新实例(修改字段)
bob_updated = bob._replace(age=31)
6. 元组与列表对比
| 特性 | 元组 | 列表 |
|---|---|---|
| 可变性 | ❌ 不可变 | ✅ 可变 |
| 内存 | 较小 | 较大 |
| 性能 | 更快 | 较慢 |
| 功能 | 基本序列操作 | 增删改查全套 |
| 使用场景 | 数据保护/字典键 | 动态数据集合 |
三、对象(range)
range 类型表示不可变的数字序列,通常用于在 for 循环中循环指定的次数。
1. 基本特性
-
不可变数字序列:生成等差数列,常用于循环
-
惰性计算:不直接存储所有值,动态计算元素(Python 3改进)
-
内存高效:无论范围多大,只存储
start/stop/step三个值 -
支持索引:可像列表一样用
r[i]访问元素
2. 三种创建方式
range(stop) # 0 ≤ x < stop,步长1
range(start, stop) # start ≤ x < stop,步长1
range(start, stop, step) # start开始,步长step
3. 参数规则
| 参数 | 默认值 | 要求 |
|---|---|---|
start | 0 | 整数(含负整数) |
stop | 无 | 序列不包含此值 |
step | 1 | 非零整数 |
特殊情形:
step > 0:递增序列(r[i] < stop)
step < 0:递减序列(r[i] > stop)
step == 0:触发ValueError
4. 经典示例
# 基础范围
list(range(5)) # [0, 1, 2, 3, 4]
list(range(2, 8)) # [2, 3, 4, 5, 6, 7]
# 指定步长
list(range(0, 10, 2)) # [0, 2, 4, 6, 8]
list(range(5, -5, -1)) # [5,4,3,2,1,0,-1,-2,-3,-4]
# 空范围
list(range(0)) # []
list(range(5, 3)) # []
list(range(0, 10, -1)) # [](方向矛盾)
5. 实际应用场景
5.1 固定次数循环
for i in range(3):
print(f"执行第{i+1}次")
# 输出:执行第1次 → 执行第3次
5.2 生成索引序列
colors = ['红', '绿', '蓝']
for i in range(len(colors)):
print(f"索引{i}: {colors[i]}")
5.3 数值序列生成
even_numbers = list(range(0, 10, 2)) # [0, 2, 4, 6, 8]
5.4 反向迭代
for i in range(5, 0, -1):
print(f"倒计时: {i}")
# 输出:5 → 4 → 3 → 2 → 1
6. 支持的操作
| 操作 | 示例 | 说明 |
|---|---|---|
| 索引 | range(10)[3] | 返回3 |
| 切片 | range(10)[2:5] | 返回range(2, 5) |
| 长度 | len(range(5)) | 返回5 |
| 包含检测 | 5 in range(10) | 返回True |
| 计数 | range(10).count(3) | 返回1 |
| 索引查找 | range(10).index(4) | 返回4 |
不支持:拼接(
+)、重复(*)、直接修改元素
小编有感,写在最后:列表、元组、对象都是重要的数据类型,在后续学习中也总是离不开他们的身影,所以要反复复习巩固哦~
今日的笔记涉及部分函数,现在看不太懂很正常,等我们后面再学习了函数就会将知识都串联起来,形成通路自然就了解啦~
577

被折叠的 条评论
为什么被折叠?



