集合类型
集合的创建
集合(set)是无序、不重复的元素集合,用花括号 {} 表示:
# 创建集合
fruits = {"苹果", "香蕉", "橘子"}
numbers = {1, 2, 3, 4, 5}
# 注意:空集合必须用set(),不能用{}
empty = set() # 这是空集合
empty_dict = {} # 这是空字典
# 从其他类型创建
list_to_set = set([1, 2, 2, 3, 3, 3])
print(list_to_set) # {1, 2, 3}
str_to_set = set("Hello")
print(str_to_set) # {'H', 'e', 'l', 'o'}(自动去重)
# 集合推导式
squares = {x**2 for x in range(1, 6)}
print(squares) # {1, 4, 9, 16, 25}
注意:集合中的元素必须是不可变类型(数字、字符串、元组),不能包含列表或字典。
集合的基本操作
fruits = {"苹果", "香蕉", "橘子"}
# 添加元素
fruits.add("西瓜")
print(fruits) # {'苹果', '香蕉', '橘子', '西瓜'}
# update() - 添加多个元素
fruits.update(["葡萄", "芒果"])
print(fruits)
# 删除元素
fruits.remove("苹果") # 元素不存在会报KeyError
fruits.discard("不存在") # 元素不存在不会报错
# pop() - 删除并返回任意一个元素
popped = fruits.pop()
print(popped)
# clear() - 清空集合
fruits.clear()
print(fruits) # set()
集合运算
集合支持数学中的集合运算:
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
# 并集(所有元素)
print(A | B) # {1, 2, 3, 4, 5, 6, 7, 8}
print(A.union(B)) # 同上
# 交集(共同元素)
print(A & B) # {4, 5}
print(A.intersection(B)) # 同上
# 差集(A有B没有的元素)
print(A - B) # {1, 2, 3}
print(A.difference(B)) # 同上
# 对称差集(不同时在A和B中的元素)
print(A ^ B) # {1, 2, 3, 6, 7, 8}
print(A.symmetric_difference(B)) # 同上
集合关系判断
A = {1, 2, 3}
B = {1, 2, 3, 4, 5}
C = {6, 7, 8}
# 子集判断
print(A.issubset(B)) # True(A是B的子集)
print(A <= B) # True
# 超集判断
print(B.issuperset(A)) # True(B是A的超集)
print(B >= A) # True
# 不相交判断
print(A.isdisjoint(C)) # True(A和C没有交集)
不可变集合
frozenset 是不可变版本的集合,可以作为字典的键或集合的元素:
fs = frozenset([1, 2, 3, 4, 5])
# 不能修改
# fs.add(6) # AttributeError
# 可以用于
nested_sets = {frozenset([1, 2]), frozenset([3, 4])}
print(nested_sets)
# 作为字典键
locations = {
frozenset(["北京", "天津"]): "华北",
frozenset(["上海", "杭州"]): "华东"
}
集合推导式
# 基本推导式
squares = {x**2 for x in range(10)}
# {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
# 带条件过滤
even_squares = {x**2 for x in range(10) if x % 2 == 0}
# {0, 4, 16, 36, 64}
# 字符串处理
words = ["hello", "world", "python", "hello"]
unique_lengths = {len(word) for word in words}
# {5, 6}
# 找出两个列表的共同元素
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 6, 7, 8]
common = {x for x in list1 if x in list2}
# {4, 5}
常用模式
列表去重
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
# 方法1:简单去重(不保持顺序)
unique = list(set(numbers))
print(unique) # [1, 2, 3, 4]
# 方法2:保持顺序的去重
seen = set()
unique_ordered = []
for num in numbers:
if num not in seen:
seen.add(num)
unique_ordered.append(num)
print(unique_ordered) # [1, 2, 3, 4]
# 方法3:使用dict.fromkeys()(Python 3.7+保持顺序)
unique_ordered = list(dict.fromkeys(numbers))
快速成员检测
# 集合的成员检测比列表快得多
large_list = list(range(1000000))
large_set = set(range(1000000))
import timeit
# 列表查找
list_time = timeit.timeit("999999 in large_list", globals=globals(), number=100)
# 集合查找
set_time = timeit.timeit("999999 in large_set", globals=globals(), number=100)
print(f"列表: {list_time:.4f}秒")
print(f"集合: {set_time:.6f}秒")
# 集合查找通常比列表快100倍以上
数据分析
# 分析用户行为
users_day1 = {"Alice", "Bob", "Charlie", "David"}
users_day2 = {"Bob", "David", "Eve", "Frank"}
users_day3 = {"Alice", "Charlie", "Eve", "George"}
# 三天都活跃的用户
always_active = users_day1 & users_day2 & users_day3
print(f"始终活跃: {always_active}")
# 至少活跃一天的用户
all_users = users_day1 | users_day2 | users_day3
print(f"所有用户: {all_users}")
# 仅在第一天活跃的用户
only_day1 = users_day1 - users_day2 - users_day3
print(f"仅第一天活跃: {only_day1}")
# 活跃天数统计
from collections import Counter
activity = Counter()
for user in users_day1:
activity[user] += 1
for user in users_day2:
activity[user] += 1
for user in users_day3:
activity[user] += 1
print(f"活跃天数: {dict(activity)}")
标签系统
# 文章标签
article1_tags = {"Python", "编程", "入门"}
article2_tags = {"Python", "进阶", "面向对象"}
article3_tags = {"JavaScript", "前端", "入门"}
# 找出Python相关的文章
all_tags = {"Python", "JavaScript", "编程", "前端", "入门", "进阶", "面向对象"}
python_articles = [article1_tags, article2_tags]
# 共同标签
common_tags = article1_tags & article2_tags
print(f"共同标签: {common_tags}") # {'Python'}
# 所有标签
all_article_tags = article1_tags | article2_tags | article3_tags
print(f"所有标签: {all_article_tags}")
frozenset的应用
# 作为字典键存储配置
permissions = {
frozenset(["read"]): "只读用户",
frozenset(["read", "write"]): "编辑用户",
frozenset(["read", "write", "admin"]): "管理员"
}
user_perms = frozenset(["read", "write"])
print(permissions[user_perms]) # 编辑用户
# 在集合中存储集合
nested = {frozenset([1, 2]), frozenset([3, 4])}
print(len(nested)) # 2
集合的局限性
# 不能存储可变类型
# {[1, 2]} # TypeError: unhashable type: 'list'
# 不能索引
s = {1, 2, 3}
# s[0] # TypeError: 'set' object is not subscriptable
# 无序,不能依赖顺序
s = {3, 1, 2}
print(s) # 可能是 {1, 2, 3} 或 {3, 1, 2}
总结
集合是Python中用于去重和集合运算的高效数据结构。掌握了集合的创建、运算和应用场景后,你就能更优雅地处理数据去重、成员检测和关系分析等问题。至此,Python基础数据类型的学习已完成,你已经具备了编写Python程序的核心能力。