> 技术文档 > Python Day 8 元组(tuple)与集合(set)及例题分享_python tuple和set

Python Day 8 元组(tuple)与集合(set)及例题分享_python tuple和set


一、元组(tuple)

元组是用于存储多个数据的容器,底层基于线性表结构,具有不可变特性,性能优于列表

1. 元组的基本特性
  • 不可变性:创建后长度不可变,存储的数据地址不可变(但允许存储可变数据类型,如列表,且可变元素内部可修改)。
  • 标记方式:使用小括号 () 包裹元素,元素间用逗号分隔。
  • 性能优势:因不可变特性,操作效率高于列表。
2. 元组的创建方式
  • 字面量定义

    # 空元组a = ()# 长度为1的元组(必须加逗号,否则视为普通数据)b = (1,) # 正确定义,类型为tuplec = 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. 元组的操作与运算
  • 运算符支持

    • +:拼接元组(返回新元组,原元组不变)
    • *:重复元组元素(返回新元组)
    • 关系运算符(><== 等):按元素依次比较大小
    • 成员运算符(innot 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_chineseprint(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 # 猜对后退出循环