Python Day 8 元组(tuple)与集合(set)及例题分享
·
一、元组(tuple)
元组是用于存储多个数据的容器,底层基于线性表结构,具有不可变特性,性能优于列表。
1. 元组的基本特性
- 不可变性:创建后长度不可变,存储的数据地址不可变(但允许存储可变数据类型,如列表,且可变元素内部可修改)。
- 标记方式:使用小括号
()包裹元素,元素间用逗号分隔。 - 性能优势:因不可变特性,操作效率高于列表。
2. 元组的创建方式
-
字面量定义
# 空元组 a = () # 长度为1的元组(必须加逗号,否则视为普通数据) b = (1,) # 正确定义,类型为tuple c = 1,5,3, # 省略括号也可定义元组,类型为tuple # 普通元组 tp = (3, 1, 'a', 1) -
工厂函数
tuple():将可迭代对象(如字符串、列表)转换为元组tp1 = tuple() # 空元组 tp2 = tuple('abc') # 结果:('a', 'b', 'c') tp3 = tuple([2, 1, 4]) # 结果:(2, 1, 4)
3. 元组的遍历方式
支持三种遍历方式,与列表类似:
tp = (1, 2, 3, [4, 5])
# 1. 基于索引遍历
for i in range(len(tp)):
print(tp[i])
# 2. 基于值遍历
for val in tp:
print(val)
# 3. 基于索引和值遍历(enumerate函数)
for idx, val in enumerate(tp):
print(idx, val)
4. 元组的操作与运算
-
运算符支持
+:拼接元组(返回新元组,原元组不变)*:重复元组元素(返回新元组)- 关系运算符(
>,<,==等):按元素依次比较大小 - 成员运算符(
in,not in):判断元素是否存在
tp1 = (1, 2) tp2 = (3, 4) print(tp1 + tp2) # 结果:(1, 2, 3, 4) print(tp1 * 2) # 结果:(1, 2, 1, 2) -
切片操作:仅支持提取数据,语法
[start:end:step]tp = (1, 2, 3, 4, 5) print(tp[1:4]) # 结果:(2, 3, 4)(提取索引1到3的元素)
5. 注意点
- 元组中存储的可变元素(如列表)可修改内部数据:
tp = (1, [2, 3]) tp[1].append(4) # 允许修改列表内部元素,结果:(1, [2, 3, 4])
二、集合(set)
集合是用于存储多个数据的容器,底层基于哈希表(散列表),具有无序性和去重性,不允许存储可变数据类型。
1. 集合的基本特性
- 无序性:元素存储顺序不固定,无法通过索引访问。
- 去重性:自动去除重复元素。
- 不可存储可变类型:如列表、字典等(因可变类型无法哈希)。
- 标记方式:使用大括号
{}包裹元素(空集合需用set()定义,否则{}视为字典)。
2. 集合的创建方式
-
字面量定义(不可用于创建空集合)
set1 = {1, 2, 3} # 普通集合 set2 = {1, 2, 2, 3} # 自动去重,结果:{1, 2, 3} -
工厂函数
set()set3 = set() # 空集合(正确方式) set4 = set([1, 2, 3]) # 从列表转换,结果:{1, 2, 3} -
集合生成推导式:
{表达式 for 变量 in 可迭代对象 [if 条件]}set5 = {x for x in range(1, 5)} # 结果:{1, 2, 3, 4}
3. 集合的基本操作
-
添加元素:
add(x)(添加单个元素)s = {1, 2} s.add(3) # 结果:{1, 2, 3} -
删除元素
remove(x):删除指定元素,若元素不存在则报错。discard(x):删除指定元素,元素不存在时不报错。pop():随机删除一个元素(因无序性)。
s = {1, 2, 3} s.remove(2) # 结果:{1, 3} s.discard(4) # 无操作,不报错 s.pop() # 随机删除一个元素,如结果:{3} -
清空集合:
clear()s.clear() # 结果:set()
4. 集合的运算(基于数学集合概念)
| 运算类型 | 方法 / 运算符 | 说明 | |
|---|---|---|---|
| 并集 | union(set) 或 ` |
` | 合并两个集合的所有元素(去重) |
| 交集 | intersection(set) 或 & |
取两个集合的共同元素 | |
| 差集 | difference(set) 或 - |
取属于 A 但不属于 B 的元素 | |
| 补集(对称差集) | symmetric_difference(set) 或 ^ |
取属于 A 或 B 但不同时属于两者的元素 |
-
示例
s1 = {1, 2, 3} s2 = {3, 4, 5} print(s1 | s2) # 并集:{1, 2, 3, 4, 5} print(s1 & s2) # 交集:{3} print(s1 - s2) # 差集:{1, 2} -
原地修改运算:
update()(并集)、intersection_update()(交集)等,直接修改原集合s1.update(s2) # s1变为并集结果:{1, 2, 3, 4, 5}
5. 集合的关系判断
-
子集与超集
issubset(set):判断当前集合是否为另一个集合的子集。issuperset(set):判断当前集合是否为另一个集合的超集。- 运算符:
<=(子集)、<(真子集)、>=(超集)、>(真超集)。
-
不相交判断:
isdisjoint(set):两个集合无共同元素则返回True。 -
示例
s1 = {1, 2, 3} s2 = {2, 3} print(s2.issubset(s1)) # True(s2是s1的子集) print(s1 > s2) # True(s1是s2的真超集) print(s1.isdisjoint({4, 5})) # True(无交集)
总结
- 元组:不可变容器,适合存储固定数据,支持索引访问和切片,性能优异。
- 集合:无序、去重容器,基于哈希表,适合去重、集合运算(交 / 并 / 差集)等场景,不支持索引。
一、列表排序与嵌套列表处理
1. 二维列表按默认规则排序
# 定义包含姓名和成绩的二维列表
cj = [['小明', 80], ['小红', 95], ['小强', 70]]
# 默认按列表第一个元素(字符串)排序,reverse=True 表示降序
cj.sort(reverse=True)
print(cj) # 输出:[['小强', 70], ['小红', 95], ['小明', 80]]
# 注:字符串排序按 Unicode 编码顺序('小' 开头的姓名按拼音首字母排序)
2. 嵌套列表扁平化(展开为一维列表)
ls = [[1], [2, 3], [4]]
# 列表推导式:外层循环遍历子列表,内层循环提取子列表元素
new_ls = [x for i in ls for x in i]
print(new_ls) # 输出:[1, 2, 3, 4]
二、列表元素判断与删除
1. 判断列表中是否存在连续重复元素
ls = [1, 2, 2, 3]
# 遍历列表(索引从0到倒数第2个元素)
for i in range(len(ls) - 1):
# 比较当前元素与下一个元素
if ls[i] == ls[i + 1]:
print('存在连续重复元素')
break # 找到后退出循环
else:
# 循环正常结束(未触发break),说明无连续重复
print('不存在连续重复元素')
# 输出:存在连续重复元素
2. 删除列表中所有指定元素
ls = ['1', '5', '7878', '55', '6', '4', '1', '3', '5', '1', 'a', 'a']
print(f'列表内容为{ls}')
n = input('请输入你要删除的元素:')
# 循环删除所有匹配元素(remove() 每次删除第一个匹配项)
while n in ls:
ls.remove(n)
print(f'删除后的列表为{ls}')
# 示例:若输入 '1',输出删除所有 '1' 后的列表
三、列表自定义排序与推导式
1. 按字符串长度排序
ls = ['12', '4654', 'abca', '46541645498']
# key=lambda i:len(i) 表示按元素长度排序,reverse=True 降序
ls.sort(key=lambda i: len(i), reverse=True)
print(ls) # 输出:['46541645498', '4654', 'abca', '12']
2. 生成无重复数字的三位数(1-3 组成)
# 推导式生成所有由1-3组成的三位数,且各位数字不重复
ls = [
i * 100 + j * 10 + k # 拼接百位、十位、个位
for i in range(1, 4) # 百位:1-3
for j in range(1, 4) # 十位:1-3
for k in range(1, 4) # 个位:1-3
if i != k and i != j and k != j # 条件:三个数字互不相等
]
print(ls) # 输出:[123, 132, 213, 231, 312, 321]
# 生成所有由1-3组成的三位数(允许重复)
ls = [
i * 100 + j * 10 + k
for i in range(1, 4)
for j in range(1, 4)
for k in range(1, 4)
]
print(ls) # 输出:[111, 112, 113, ..., 333](共27个)
四、集合操作(课程选修情况分析)
# 定义各课程选修学生集合
set_chinese = {'张三', '李四', '王五', '赵六'} # 语文
set_math = {'李四', '王五'} # 数学
set_english = {'张三', '赵六'} # 英语
# 所有选修过至少一门课程的学生(并集)
set_all = set_math | set_english | set_chinese # 等价于 set_math.union(set_english, set_chinese)
# 只选修语文的学生(语文减去数学和英语的并集)
set_chinese_1 = set_chinese - (set_math | set_english)
# 三门课程都选修的学生(交集,数学和英语的交集与数学再交,结果为空)
set_3 = set_math & set_english & set_chinese
print(f'所有课程对应的学生{set_all}') # 输出:{'张三', '李四', '王五', '赵六'}
print(f'只选修语文的学生{set_chinese_1}') # 输出:set()(因所有语文学生都选了其他课)
print(f'三门课程都选修的学生{set_3}') # 输出:set()
五、元组与列表结合处理
将元组作为键,列表作为值,组合成键值对列表
# 定义字段名元组
tp = ("name", "age", "sex")
# 定义学生信息列表(每个元素是包含姓名、年龄、性别的列表)
ls = [("张三", 20, "男"), ("李四", 20, "女")]
ls_new = []
# 遍历学生信息
for i in ls:
# 遍历每个学生的信息,结合字段名生成键值对
for idx, x in enumerate(i):
ls_new.append((tp[idx], x)) # (字段名, 值)
print(ls_new)
# 输出:[('name', '张三'), ('age', 20), ('sex', '男'), ('name', '李四'), ('age', 20), ('sex', '女')]
六、经典问题:报数淘汰(每 7 个淘汰一个)
# 生成1-15的列表(代表15个人)
ls = list(range(1, 16))
i = 1 # 计数变量,记录当前报数
# 当列表长度大于1时继续循环(直到剩下1人)
while len(ls) > 1:
if i % 7 != 0:
# 未报到7,将第一个人移到列表末尾(模拟循环报数)
ls.append(ls[0])
ls.remove(ls[0])
else:
# 报到7,淘汰第一个人
ls.remove(ls[0])
i += 1 # 报数递增
print(ls) # 输出:[1](最终剩下的人)
七、猜数字游戏(随机数猜测)
import random
# 生成1-100的随机整数
a = random.randint(1, 100)
# 循环猜测直到猜对
while True:
b = int(input('猜一下:'))
if b > a:
print('猜大了')
elif b < a:
print('猜小了')
else:
print('猜对了!!!!!')
break # 猜对后退出循环更多推荐
所有评论(0)