展开菜单
首页 精品内容 本月促销 装机必备 Windows macOS软件 IOS软件 Android AI PDF教程 专题
全部分类

当前位置:

首页 > 编程开发 > Python基础指南之集合set的创建与自动去重详解

Python基础指南之集合set的创建与自动去重详解

集合是Python内置容器类型,具有元素唯一、无序和可变特性。创建可用花括号或set()构造函数,自动去重基于哈希表和相等性比较,增删改操作包括add、remove、discard、pop等。集合成员检测时间复杂度为O(1),适用于高效去重和成员检测场景。

聊聊集合(set)——这个数据类型在Python里其实挺“特立独行”的。

先看一个生活中常见的场景:你手里有一份包含1000条用户访问记录的文件,现在想知道到底有多少个不同的IP访问了你的网站。如果只会用列表,你得写一个循环,逐一判断每个IP是否已经记录过,代码笨重且低效。

Python基础指南之集合set的创建与自动去重详解

但如果用Python的集合(set),一行代码就搞定了:

ip_list = ['192.168.1.1', '10.0.0.5', '192.168.1.1', '172.16.0.3', '10.0.0.5']
unique_ips = set(ip_list)
print(unique_ips)  # {'192.168.1.1', '10.0.0.5', '172.16.0.3'}
print(f'独立IP数量: {len(unique_ips)}')  # 3

集合是Python内置的四大核心容器类型之一(列表、元组、字典、集合)。它有两个最独特的天性:元素不重复无序性。这两个特性让它成为去重、成员检测、集合运算(交并差)的最佳选择。

今天这篇文章,我们来深入拆解集合的创建方式和自动去重特性。下一篇我们会讲集合的交并差运算。

二、集合的基本概念

2.1 什么是集合?

集合就是一个无序的、元素唯一的容器。它和数学里的“集合”概念一脉相承——集合中的元素不能重复,而且“{1, 2}”和“{2, 1}”是同一个集合(因为没有顺序)。

# 集合的三个核心特征
# 1. 元素唯一(自动去重)
s = {1, 2, 2, 3, 3, 3}
print(s)  # {1, 2, 3}——重复的2和3被自动去掉了

# 2. 无序——元素的存储顺序和插入顺序无关
s = {3, 1, 4, 1, 5, 9, 2, 6}
print(s)  # 输出顺序通常不是你插入的顺序

# 3. 可变——可以添加和删除元素(但元素本身必须是不可变的)
s = {1, 2, 3}
s.add(4)      # ✅ 可以添加
s.remove(1)   # ✅ 可以删除
print(s)      # {2, 3, 4}

2.2 集合在Python类型体系中的位置

集合和列表、字典一样是可变类型。但集合中的元素必须是不可变(可哈希)类型。这意味着:

# ✅ 这些可以放进集合——都是不可变类型
valid_set = {1, 3.14, 'hello', (1, 2), True, None, frozenset([1, 2])}
print(valid_set)

# ❌ 这些不能放进集合——是可变类型
# {[1, 2]}      # TypeError: unhashable type: 'list'
# {{'a': 1}}    # TypeError: unhashable type: 'dict'
# {{1, 2}}      # TypeError: unhashable type: 'set'(除非用frozenset)

这和字典的“键”的要求是一样的——因为集合底层也是基于哈希表实现的,和字典共用同一套数据结构。

2.3 集合 vs 列表 vs 字典

特性列表(list)字典(dict)集合(set)
元素唯一❌ 可重复✅ 键唯一✅ 元素唯一
有序性✅ 有序✅ 保序(3.7+)❌ 无序
可变性✅ 可变✅ 可变✅ 可变
索引访问lst[0]d[key]❌ 不支持
查找速度O(n)O(1)O(1)
底层结构动态数组哈希表哈希表

三、创建集合的N种方式

3.1 花括号直接创建

# 最基本的方式——用花括号
fruits = {'apple', 'banana', 'orange'}
print(fruits)  # {'banana', 'orange', 'apple'}
print(type(fruits))  # 

# 空集合——⚠️ 必须用set(),因为{}是空字典!
empty_set = set()
print(type(empty_set))  # 

empty_dict = {}
print(type(empty_dict))  # ——注意区别!

# 集合中的元素自动去重
numbers = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4}
print(numbers)  # {1, 2, 3, 4}
print(len(numbers))  # 4(不是10)

3.2 set()构造函数——从任何可迭代对象创建

# set()接受任何可迭代对象

# 从列表创建
s1 = set([1, 2, 3, 2, 1])
print(s1)  # {1, 2, 3}

# 从元组创建
s2 = set((10, 20, 30, 20))
print(s2)  # {10, 20, 30}

# 从字符串创建——每个字符成为一个元素
s3 = set('hello world')
print(s3)  # {'h', 'e', 'l', 'o', ' ', 'w', 'r', 'd'}
# 注意:两个'l'和两个'o'各只保留一个

# 从range对象创建
s4 = set(range(10))
print(s4)  # {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

# 从字典创建(取键)
s5 = set({'a': 1, 'b': 2, 'c': 3})
print(s5)  # {'a', 'b', 'c'}

# 从生成器表达式创建
s6 = set(x ** 2 for x in range(5))
print(s6)  # {0, 1, 4, 9, 16}

# 从文件对象创建(每行一个元素)
# with open('file.txt') as f:
#     lines = set(f)  # 自动去重的行集合

3.3 创建包含各种类型元素的集合

# 混合类型集合
mixed = {42, 'hello', 3.14, True, None, (1, 2)}
print(mixed)  # {False, 3.14, 'hello', 42, None, (1, 2)}

# ⚠️ 注意:True在集合中等于1,False等于0
# 因为bool是int的子类,True==1, False==0
numbers_with_bool = {1, True, 2, False, 0, 3}
print(numbers_with_bool)  # {0, 1, 2, 3}——True和1合并了,False和0合并了

# 验证
print(True == 1)   # True
print(False == 0)  # True
print({1, True})   # {1}——因为是同一个值
print({0, False})  # {0}——同理

四、自动去重特性的深度理解

4.1 去重的依据:hash__和__eq

集合判断两个元素是否“相同”,依据的是哈希值和相等性比较:

# 去重流程:
# 1. 计算新元素的哈希值 hash(element)
# 2. 找到哈希表中对应位置
# 3. 如果该位置已有元素,用 == 比较
# 4. 如果相等,则不插入(去重)
# 5. 如果不等(哈希冲突),用开放地址法探测下一个位置

# 演示:自定义类的去重行为
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __hash__(self):
        """定义哈希值——基于name"""
        return hash(self.name)
    
    def __eq__(self, other):
        """定义相等性——基于name和age"""
        if not isinstance(other, Person):
            return False
        return self.name == other.name and self.age == other.age
    
    def __repr__(self):
        return f'Person({self.name}, {self.age})'


# 哈希相同但==不相等 → 两个元素都保留(哈希冲突)
p1 = Person('Alice', 25)  # hash基于'Alice'
p2 = Person('Alice', 30)  # hash还是基于'Alice',但age不同
s = {p1, p2}
print(s)  # {Person(Alice, 25), Person(Alice, 30)}——两个都保留

# 哈希相同且==相等 → 去重
p3 = Person('Alice', 25)  # 和p1一模一样
p4 = Person('Alice', 25)  # 也和p1一模一样
s2 = {p1, p3, p4}
print(s2)  # {Person(Alice, 25)}——只有一个

4.2 各种类型的去重行为

# 整数——按数值去重
s = {1, 2, 3, 1, 2}
print(s)  # {1, 2, 3}

# 浮点数——按数值去重
s = {1.0, 2.0, 1.0, 3.0}
print(s)  # {1.0, 2.0, 3.0}

# ⚠️ 注意:1和1.0在集合中是一样的!
s = {1, 1.0, 2, 3}
print(s)  # {1, 2, 3}——1和1.0被视为相同
print(1 == 1.0)  # True
print(hash(1))   # 1
print(hash(1.0)) # 1——相同的哈希值!

# 字符串——按内容去重
s = {'hello', 'world', 'hello', 'HELLO'}
print(s)  # {'hello', 'world', 'HELLO'}——'hello'被去重,'HELLO'不同

# 元组——按内容去重
s = {(1, 2), (3, 4), (1, 2), (2, 1)}
print(s)  # {(1, 2), (3, 4), (2, 1)}——(1,2)去重,(2,1)是不同元组

# None——只有一个None
s = {None, None, None}
print(s)  # {None}

4.3 去重的实际性能

集合的去重依赖哈希表,查询和插入的平均时间复杂度都是O(1),所以大批量数据的去重非常快:

import time
import random

# 生成10万个有重复的整数
data = [random.randint(1, 10000) for _ in range(100000)]

# 方法一:手动去重(用列表 + in 检查)
start = time.perf_counter()
unique_list = []
for x in data:
    if x not in unique_list:  # O(n)每次
        unique_list.append(x)
print(f'手动去重: {time.perf_counter() - start:.4f}s,结果数量: {len(unique_list)}')

# 方法二:用集合去重
start = time.perf_counter()
unique_set = set(data)  # O(1)每次,总共O(n)
print(f'集合去重: {time.perf_counter() - start:.4f}s,结果数量: {len(unique_set)}')

# 性能差异通常有数百倍到数千倍!

五、集合的增删改操作

虽然我们后面会详细讲集合操作,但这里先快速了解一下基本增删:

5.1 添加元素

s = {1, 2, 3}

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

# 添加重复元素——静默忽略,不报错
s.add(4)
print(s)  # {1, 2, 3, 4}——还是原来的样子

# update()——批量添加(从可迭代对象)
s.update([5, 6, 7])
print(s)  # {1, 2, 3, 4, 5, 6, 7}

s.update({8, 9}, (10, 11))
print(s)  # {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}

# update也可以接受字符串(逐个字符添加)
s2 = set()
s2.update('abc')
print(s2)  # {'a', 'b', 'c'}

5.2 删除元素

s = {1, 2, 3, 4, 5}

# remove()——删除指定元素,不存在则报错
s.remove(3)
print(s)  # {1, 2, 4, 5}
# s.remove(99)  # KeyError: 99

# discard()——删除指定元素,不存在也不报错
s.discard(4)
print(s)  # {1, 2, 5}
s.discard(99)  # 不报错

# pop()——随机删除并返回一个元素
# ⚠️ 注意:集合无序,pop()删除的是"任意"一个元素
popped = s.pop()
print(f'弹出: {popped}, 剩余: {s}')

# clear()——清空集合
s.clear()
print(s)  # set()

5.3 删除操作的对比表

方法行为元素不存在时返回值
remove(x)删除xKeyErrorNone
discard(x)删除x不报错None
pop()删除任意一个KeyError(集合为空)被删除的元素
clear()删除所有不报错None

六、集合的成员检测和遍历

6.1 成员检测——O(1)的查找速度

# 集合最大的性能优势:成员检测是O(1)
# 列表的成员检测是O(n),集合是O(1)

s = set(range(100000))

import time

# 集合查找
start = time.perf_counter()
for _ in range(1000):
    _ = 99999 in s
print(f'集合in: {time.perf_counter() - start:.6f}s')

# 列表查找(对比)
lst = list(range(100000))
start = time.perf_counter()
for _ in range(1000):
    _ = 99999 in lst
print(f'列表in: {time.perf_counter() - start:.6f}s')

# 实际示例:快速过滤
all_users = {'alice', 'bob', 'charlie', 'da vid', 'eve', 'frank', 'grace'}
vip_users = {'alice', 'charlie', 'grace'}

# 检查是否是VIP——O(1)
print('alice' in vip_users)    # True
print('bob' in vip_users)      # False

# 检查是否有访问权限
def has_access(username):
    return username in all_users

print(has_access('hacker'))  # False

6.2 遍历集合

s = {'apple', 'banana', 'orange', 'grape', 'mango'}

# for循环遍历——顺序不保证!
print('遍历集合:')
for fruit in s:
    print(f'  {fruit}', end='')
print()

# 排序后遍历
print('排序后遍历:')
for fruit in sorted(s):
    print(f'  {fruit}', end='')
print()

# 按长度排序遍历
print('按长度排序:')
for fruit in sorted(s, key=len):
    print(f'  {fruit}({len(fruit)})', end='')
print()

# enumerate遍历(带序号)
print('带序号遍历:')
for i, fruit in enumerate(s, 1):
    print(f'  {i}. {fruit}')

# ⚠️ 遍历时不能修改集合!
# for item in s:
#     s.add('new')  # RuntimeError: Set changed size during iteration

七、集合的常用内置操作

7.1 基础信息操作

s = {1, 2, 3, 4, 5}

# len()——元素个数
print(len(s))  # 5

# max() / min()——最大/最小元素
print(max(s))  # 5
print(min(s))  # 1

# sum()——求和
print(sum(s))  # 15

# any() / all()
print(any({0, False, 1}))  # True(至少有一个为真)
print(all({1, True, 2}))   # True(全部为真)
print(all({0, 1, 2}))      # False(0为假)

7.2 集合之间的关系判断

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

# 判断子集
print(a.issubset(b))      # True——a是b的子集
print(a <= b)             # True——运算符写法
print(a < b)              # True——真子集(a⊂b,不等于b)

# 判断超集
print(b.issuperset(a))    # True——b是a的超集
print(b >= a)             # True——运算符写法
print(b > a)              # True——真超集

# 判断相等(内容相同)
print(a == c)             # True
print(a == b)             # False

# 判断不相交
d = {4, 5, 6}
print(a.isdisjoint(d))    # True——没有公共元素
print(a.isdisjoint(b))    # False——有公共元素(1,2,3)

八、实战场景

8.1 场景一:数据去重与清洗

# 场景:从用户行为日志中提取不同的操作类型
log_entries = [
    'LOGIN - alice',
    'LOGOUT - alice',
    'LOGIN - bob',
    'PURCHASE - alice',
    'LOGIN - alice',      # 重复操作
    'VIEW_PAGE - charlie',
    'LOGIN - bob',         # 重复操作
    'PURCHASE - bob',
    'VIEW_PAGE - alice',
    'LOGOUT - bob',
]

# 提取所有不同的操作类型
action_types = {entry.split(' - ')[0] for entry in log_entries}
print(f'操作类型: {action_types}')
# {'LOGIN', 'LOGOUT', 'PURCHASE', 'VIEW_PAGE'}

# 提取所有不同的用户
users = {entry.split(' - ')[1] for entry in log_entries}
print(f'活跃用户: {users}')
# {'alice', 'bob', 'charlie'}

8.2 场景二:成员白名单/黑名单

# 场景:API接口的IP黑白名单
class IPFilter:
    """IP黑白名单过滤器——用集合实现O(1)查找"""
    
    def __init__(self):
        self._whitelist = set()  # 白名单(优先)
        self._blacklist = set()  # 黑名单
    
    def add_whitelist(self, ip):
        self._whitelist.add(ip)
    
    def add_blacklist(self, ip):
        self._blacklist.add(ip)
    
    def remove_whitelist(self, ip):
        self._whitelist.discard(ip)
    
    def remove_blacklist(self, ip):
        self._blacklist.discard(ip)
    
    def is_allowed(self, ip):
        """判断IP是否允许访问"""
        # 白名单优先——白名单中的IP即使同时在黑名单中也允许
        if ip in self._whitelist:
            return True
        # 在黑名单中
        if ip in self._blacklist:
            return False
        # 都不在——默认允许
        return True
    
    def load_from_file(self, filename, list_type):
        """从文件加载IP列表"""
        target = self._whitelist if list_type == 'whitelist' else self._blacklist
        with open(filename) as f:
            for line in f:
                ip = line.strip()
                if ip:
                    target.add(ip)
        print(f'已加载 {len(target)} 个IP到{list_type}')


# 使用示例
ip_filter = IPFilter()
ip_filter.add_blacklist('10.0.0.99')
ip_filter.add_blacklist('192.168.1.100')
ip_filter.add_whitelist('10.0.0.1')  # 管理员IP,始终允许

# 检查
print(ip_filter.is_allowed('10.0.0.99'))     # False——黑名单
print(ip_filter.is_allowed('10.0.0.1'))      # True——白名单优先
print(ip_filter.is_allowed('172.16.0.5'))    # True——不在任何名单中

8.3 场景三:文本分析——找出不重复的单词

# 场景:分析两篇文章的词汇差异
article1 = """
Machine learning is a subset of artificial intelligence that enables
systems to learn and improve from experience without being explicitly
programmed machine learning focuses on the development of computer
programs that can access data and use it to learn for themselves
"""

article2 = """
Deep learning is a subset of machine learning in artificial intelligence
that has networks capable of learning unsupervised from data that is
unstructured or unlabeled deep learning is also known as deep neural
network learning
"""

# 提取单词集合
def extract_words(text):
    return {word.strip('.,;:!?()[]{}'"').lower() for word in text.split() if len(word) > 1}

words1 = extract_words(article1)
words2 = extract_words(article2)

print(f'文章1不同单词数: {len(words1)}')
print(f'文章2不同单词数: {len(words2)}')

# 文章1独有的单词
only_in_1 = words1 - words2
print(f'n文章1独有的词 ({len(only_in_1)}个): {only_in_1}')

# 文章2独有的单词
only_in_2 = words2 - words1
print(f'文章2独有的词 ({len(only_in_2)}个): {only_in_2}')

# 两篇文章共有的单词
common = words1 & words2
print(f'两篇共有的词 ({len(common)}个): {common}')

# 所有出现过的单词
all_words = words1 | words2
print(f'总词汇量: {len(all_words)}')

8.4 场景四:快速统计不同元素

# 场景:统计一个论坛帖子里有多少不同的参与者
# 包括发帖人和所有回复人

posts = [
    {'author': 'alice', 'replies': ['bob', 'charlie', 'bob']},
    {'author': 'bob', 'replies': ['alice', 'da vid']},
    {'author': 'charlie', 'replies': ['alice', 'eve', 'alice', 'da vid']},
    {'author': 'da vid', 'replies': ['eve']},
]

# 统计所有参与者(去重)
all_participants = set()
for post in posts:
    all_participants.add(post['author'])      # 发帖人
    all_participants.update(post['replies'])  # 回复人

print(f'参与者总数: {len(all_participants)}')
print(f'参与者名单: {all_participants}')

# 统计谁发了帖(有帖子但没回复?)
authors = {post['author'] for post in posts}
repliers = set()
for post in posts:
    repliers.update(post['replies'])

print(f'只发帖没回复的人: {authors - repliers}')
print(f'只回复没发帖的人: {repliers - authors}')
print(f'又发帖又回复的人: {authors & repliers}')

九、集合的底层原理简述

9.1 哈希表

集合底层和字典一样,使用哈希表。每个元素通过哈希函数计算出一个整数,这个整数决定了元素在哈希表中的存储位置:

# 查看元素的哈希值
print(hash('hello'))   # 某个整数(每次运行可能不同)
print(hash(42))        # 42(整数的哈希就是自己)
print(hash((1, 2, 3))) # 某个整数

# 哈希表的工作流程:
# 1. 对元素x计算 hash(x)
# 2. 用 hash(x) % table_size 确定存储槽位
# 3. 如果槽位为空,直接存储
# 4. 如果槽位已被占用(哈希冲突),用开放地址法探测下一个位置
# 5. 如果发现相等的元素(__eq__返回True),则不插入(去重)

9.2 为什么集合是无序的

# 集合的无序不是"随机",而是"按哈希值分布"
# 元素的存储位置由哈希值决定,不是插入顺序

s = set()
s.add(1)
s.add(2)
s.add(3)
print(s)  # 输出顺序通常看起来"有序",是因为小整数的哈希就是自己

# 但对字符串就不一定了
s = {'banana', 'apple', 'cherry'}
print(s)  # 输出顺序不可预测

# ⚠️ 如果你需要保序的集合,可以:
# 1. 使用字典的键(Python 3.7+保序)
ordered_unique = dict.fromkeys([3, 1, 4, 1, 5, 9, 2, 6])
print(list(ordered_unique))  # [3, 1, 4, 5, 9, 2, 6]——保序去重

# 2. 使用sorted()排序输出
print(sorted(s))  # ['apple', 'banana', 'cherry']——字母序

9.3 集合的内存占用

import sys

# 集合有一定的内存开销(维护哈希表)
numbers = list(range(1000))
lst = numbers
s = set(numbers)

print(f'列表内存: {sys.getsizeof(lst)} 字节')
print(f'集合内存: {sys.getsizeof(s)} 字节')
# 集合通常占用更多内存——这是哈希表结构的代价
# 换取的是O(1)的查找和去重能力

# 实际内容的内存还包括元素本身
# sys.getsizeof只测量容器对象本身
# 如果需要精确测量,可以用更专业的工具

十、常见陷阱与注意事项

10.1 陷阱一:空集合用{}是错的

# ❌ 这不是空集合!
empty = {}
print(type(empty))  # ——这是字典!

# ✅ 这才是空集合
empty_set = set()
print(type(empty_set))  # 

# 为什么?因为Python用{}初始化空字典的历史更早
# set字面量语法是后来添加的,必须避免歧义

10.2 陷阱二:可变元素不能放入集合

# ❌ 列表不能放入集合
# s = {[1, 2, 3]}  # TypeError: unhashable type: 'list'

# ❌ 字典不能放入集合
# s = {{'a': 1}}   # TypeError: unhashable type: 'dict'

# ❌ 集合不能放入集合
# s = {{1, 2}}     # TypeError: unhashable type: 'set'

# ✅ 但可以用frozenset
s = {frozenset([1, 2]), frozenset([3, 4])}
print(s)  # {frozenset({1, 2}), frozenset({3, 4})}

# ❌ 包含可变元素的元组也不能放入集合
# s = {(1, [2, 3])}  # TypeError: unhashable type: 'list'
# 因为元组中的列表是可变的,导致整个元组不可哈希

# ✅ 纯不可变元素的元组可以
s = {(1, 2), (3, 4)}
print(s)  # {(1, 2), (3, 4)}

10.3 陷阱三:遍历时修改集合

s = {1, 2, 3, 4, 5}

# ❌ 遍历时修改集合——会引发RuntimeError
# for x in s:
#     if x % 2 == 0:
#         s.remove(x)  # RuntimeError: Set changed size during iteration

# ✅ 正确方式一:遍历副本
for x in s.copy():
    if x % 2 == 0:
        s.remove(x)
print(s)  # {1, 3, 5}

# ✅ 正确方式二:用集合推导式创建新集合
s = {1, 2, 3, 4, 5}
s = {x for x in s if x % 2 != 0}
print(s)  # {1, 3, 5}

# ✅ 正确方式三:先收集要删除的,再统一删
s = {1, 2, 3, 4, 5}
to_remove = {x for x in s if x % 2 == 0}
s -= to_remove
print(s)  # {1, 3, 5}

10.4 陷阱四:集合是不可索引的

s = {10, 20, 30, 40, 50}

# ❌ 集合不支持索引访问
# print(s[0])  # TypeError: 'set' object is not subscriptable

# ❌ 集合不支持切片
# print(s[1:3]) # TypeError

# 如果你需要"第n个元素"——先转为列表
# 但注意:转为列表后的顺序不确定!
lst = list(s)
print(lst[0])  # 可以访问,但不知道是哪个元素

# 如果需要有序集合,用sorted
for i, item in enumerate(sorted(s)):
    print(f'{i}: {item}')

10.5 陷阱五:True和1、False和0的混淆

# ⚠️ 在集合中,True==1,False==0
s = {1, True, 0, False}
print(s)  # {0, 1}——只有两个元素

# 含义:True和1在集合中被视为同一个值
# 同理False和0也被视为同一个值
# 这是因为 bool 是 int 的子类

# 验证
print(issubclass(bool, int))  # True
print(True == 1)              # True
print(False == 0)             # True
print(hash(True))             # 1
print(hash(1))                # 1
print(hash(False))            # 0
print(hash(0))                # 0

十一、集合 vs 列表:什么时候用哪个

# 选型决策树
def choose_collection(requirements):
    """
    根据需求选择合适的集合类型
    """
    needs_order = requirements.get('order')      # 需要保持顺序
    needs_unique = requirements.get('unique')    # 需要唯一性
    needs_index = requirements.get('index')      # 需要按位置访问
    needs_search = requirements.get('search')    # 需要快速查找
    needs_modify = requirements.get('modify')    # 需要频繁修改
    
    if needs_unique and needs_search:
        if needs_order:
            return 'dict(Python 3.7+保序,键唯一,用作有序集合)'
        return 'set'  # 去重 + 快速查找
    elif needs_order and needs_index:
        return 'list'  # 保序 + 索引访问
    elif needs_unique and needs_order:
        return 'OrderedDict的键 或 dict.fromkeys()'
    else:
        return '根据具体情况选择'


# 示例
print(choose_collection({'unique': True, 'search': True}))
# set

print(choose_collection({'order': True, 'index': True}))
# list

print(choose_collection({'unique': True, 'order': True}))
# dict(Python 3.7+)

十二、本篇小结

集合是Python中专门用于去重快速查找的数据结构:

核心特性:

  • 元素唯一:自动去重(基于__hash____eq__
  • 无序:存储顺序由哈希值决定,不保证插入顺序
  • 可变:可以add、remove(但元素本身必须是不可变的)
  • O(1)查找:成员检测(in)极快

创建方式:

  • {1, 2, 3}——花括号直接创建(空集合必须用set()
  • set(iterable)——从任何可迭代对象创建
  • 集合推导式:{x for x in iterable if condition}

常用操作:

  • 增:add()(单个)、update()(批量)
  • 删:remove()(不存在报错)、discard()(不存在不报错)、pop()(随机删一个)、clear()
  • 查:in(O(1)成员检测)
  • 判断:issubset()issuperset()isdisjoint()

掌握集合的创建和去重特性后,下一篇我们将深入学习集合最强大的能力——交并差对称差运算。这些集合运算在数据处理、权限管理、图算法等领域有着极其广泛的应用。

本文内容来源于互联网,如有侵权请联系删除。
作者最新文章
编程开发 Python
相关文章 更多
精品专题 更多
本月促销

正软商城本月促销专区,汇集办公、设计、安全、影音、系统工具及AI软件等正版软件优惠活动,提供限时折扣、特价授权和优惠购买信息,活动库存及价格以页面实时展示为准。

装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

IOS软件

正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

AI

正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
灵活计算器
灵活计算器

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

图几
图几

图几是一款适用于 macOS 的截图、标注与美化工具,支持离线操作保障隐私。界面整理和高频系统操作被放到一起考虑,桌面或窗口内容一多时,管理起来会更省心。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Menuist
Menuist

Menuist 是一款面向 macOS 的 Finder 右键菜单增强工具,主要用来补充新建文件、快捷导航等常用操作,让日常文件管理和访问路径时更高效、更顺手。

Mole
Mole

Mole 是一款专为 Mac 设计的深度清理优化工具,涵盖缓存清理、应用管理及实时状态监控等功能。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

WINDOWS 更多
Windows 10
Windows 10

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

傲梅轻松备份
傲梅轻松备份

傲梅轻松备份是一款专业易用的数据备份软件,为重要数据提供安全保障。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

Wise Folder Hider Pro
Wise Folder Hider Pro

Wise Folder Hider Pro 是一款专业级文件和文件夹隐藏加密软件,为私密数据添加多重保护。高频操作更强调就近处理,浏览、整理和跨目录移动文件时,来回切换和重复点击都会少很多。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

PinStack
PinStack

PinStack是一款轻量级的Windows平台剪贴板管理工具,优化您的剪贴板使用体验。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Seer
Seer

Seer是一款在Win平台下的空格键功能增强效率工具,只需轻敲空格键,就能预览几乎任何格式的文件。它更适合把零散的小功能集中起来使用,处理高频琐碎任务时会更省事。