一、为什么需要集合
列表能装一串东西、能重复、按位置找;字典能按名字找值。但有一类需求这两个都不顺手:「这里面的东西不能重复」和「某某在不在里面」。
比如一份报名名单,同一个名字被填了两遍,要数一数到底有几个人报名:
names = ['小明', '小红', '小明', '小刚', '小红']
print('名单条数:', len(names))
print('实际人数:', len(set(names)))
输出:
名单条数: 5
实际人数: 3
用 set() 一包,重复的自动就没了。这就是集合:一袋不许重复的东西,它的长项是「去重」和「判断在不在」,而不是「排第几」。
| 容器 | 一句话 | 最擅长 |
|---|---|---|
列表 [] | 一队有顺序的人 | 按位置取、要顺序、允许重复 |
元组 () | 刻在石头上的名单 | 内容不许改 |
字典 {} | 一本词典 | 按名字(键)查值 |
集合 set() | 一袋不许重复的东西 | 去重、判断在不在、做交并差 |
课程思政|数据安全与法治素养 · 名单里每个名字都是人
集合的第一本事是去重:一份报名名单,用 set() 一包,重复的名字自动只剩一个。可别弄反了——被去掉的只是重复的登记,不等于这个人可以随便被抹掉。数据能合并、能去重,但每条记录背后都是活生生的人。以后再收集学号、手机号这类信息,多问一句该不该留、能留多久,是统计人该有的分寸。
二、创建集合的四种方式
方式一:花括号里直接写
和字典一样用花括号,但里面只有元素、没有冒号。
fruits = {'苹果', '香蕉', '龙眼'}
print(len(fruits))
print('苹果' in fruits)
输出:
3
True
方式二:用 set() 把别的序列变过来(顺手去重)
print(set([1, 2, 2, 3, 3, 3]))
print(sorted(set('hello')))
输出:
{1, 2, 3}
['e', 'h', 'l', 'o']
set() 能吃掉列表、字符串、元组、range 等任何「能一个个数出来」的东西。字符串会被拆成一个一个字符。
方式三:空集合只能写 set()
这是集合最大的一个坑:{} 是空字典,不是空集合。
s = {}
s.add(1)
运行后会报错(逐字照抄解释器):
AttributeError: 'dict' object has no attribute 'add'
括号里什么都没有时,Python 默认建的是字典。想要空集合,必须写 set():
s = set()
s.add(1)
print(s)
print(type(s))
输出:
{1}
<class 'set'>
方式四:集合推导式(先看个样子)
print({x * x for x in range(1, 6)})
输出:
{1, 4, 9, 16, 25}
写法像列表推导式,只是外面换成花括号。它天生就会去重,第八节细讲。
| 写法 | 结果 | 备注 |
|---|---|---|
{1, 2, 3} | 含 3 个元素的集合 | 最常用 |
set([1, 2, 2]) | {1, 2} | 从别的序列转过来,顺手去重 |
set() | 空集合 | 只能用这一种! |
{} | 空字典 | 别搞错 |
{x for x in range(3)} | {0, 1, 2} | 集合推导式 |
{}。它是个空字典,后面一调用集合的方法(比如 add)就报 AttributeError: 'dict' object has no attribute 'add'。请记牢:空集合写 set()。三、集合的三条规矩(不重复、无序、元素不可变)
规矩 1:不重复,重复的自动被吃掉
s = {1, 2, 2, 3, 3, 3}
print(s)
print(len(s))
输出:
{1, 2, 3}
3
规矩 2:无序——不能用下标,也不能切片
集合不记「谁排第几」,所以 s[0] 这种写法直接报错。
s = {1, 2, 3}
print(s[0])
运行后会报错(逐字照抄解释器):
TypeError: 'set' object is not subscriptable
两个后果要记住:
- 想「按顺序取第几个」,请改用列表。
print(s)出来的顺序不保证和你写进去的顺序一样(元素越多、越不是小数字,越容易看出来)。想让输出每次都固定,先sorted()。
s = {3, 1, 2}
print(sorted(s))
print(sorted(s, reverse=True))
输出:
[1, 2, 3]
[3, 2, 1]
顺带记一句:集合比的是「内容一样不一样」,跟顺序无关。
print({1, 2, 3} == {3, 2, 1})
输出:
True
规矩 3:元素必须「不可变」
集合内部要靠一个「位置」来快速找到元素,所以元素必须是算得出固定位置的东西(术语叫「可哈希」)。列表和字典会变,放不进去。
s = {[1, 2], 3}
运行后会报错(逐字照抄解释器):
TypeError: unhashable type: 'list'
能放的:数字、字符串、True/False、元组(前提是元组里装的也都是不可变的)。
s = {(1, 2), (3, 4)}
print(sorted(s))
输出:
[(1, 2), (3, 4)]
| 元素类型 | 能不能放进集合 | 为什么 |
|---|---|---|
数字 10 | 能 | 不可变 |
字符串 'abc' | 能 | 不可变 |
元组 (1, 2) | 能(里面也得都是不可变的) | 元组本身不可变 |
列表 [1, 2] | 不能 | 会变,报 unhashable |
字典 {'a': 1} | 不能 | 会变 |
集合 {1, 2} | 不能 | 普通集合会变(frozenset 才行) |
四、往里加、往外删(add / update / remove / discard / pop / clear)
集合的增删方法不多,记住下面六张「面孔」就够了。
| 方法 | 作用 | 要不要给值 |
|---|---|---|
s.add(x) | 加一个元素 | 给 |
s.update(序列) | 一次加一批 | 给 |
s.remove(x) | 删掉 x,没有就报错 | 给 |
s.discard(x) | 删掉 x,没有也不报错 | 给 |
s.pop() | 随便删掉一个并返回它 | 不给 |
s.clear() | 全部清空 | 不给 |
add:加一个(重复加等于没加)
s = {1, 2, 3}
s.add(4)
print(sorted(s))
s.add(4) # 已经有了,加了也白加
print(len(s)) # 还是 4 个
输出:
[1, 2, 3, 4]
4
注意 add() 自己不返回值,别写 s = s.add(4)——那样 s 会变成 None。
update:一次加一批
s = {1, 2}
s.update([3, 4, 4, 5])
print(sorted(s))
输出:
[1, 2, 3, 4, 5]
remove 和 discard:删一个
差别只有一个:删不存在的元素时,remove 报错,discard 当没事发生。
s = {1, 2, 3}
s.remove(99)
运行后会报错(逐字照抄解释器):
KeyError: 99
不确定在不在,就用 discard;确定在、想让它报错帮你查问题,就用 remove。
s = {1, 2, 3}
s.discard(99) # 没有,也不报错
s.remove(1) # 有,正常删掉
print(sorted(s))
输出:
[2, 3]
pop:随便删掉一个(不能指定删谁)
s = {10, 20, 30}
print(s.pop())
print(sorted(s))
输出:
10
[20, 30]
因为集合无序,「第一个」没有意义,所以 pop() 删的是随便哪个,只适合「我随便拿一个出来处理」的场景。
clear:清空
s = {1, 2, 3}
s.clear()
print(s)
print(bool(s)) # 空集合在判断里算「假」
输出:
set()
False
五、遍历与判断(for、in、len)
一个个过一遍:for
集合也能 for。因为无序,想要固定顺序就先 sorted()。
for x in sorted({3, 1, 2}):
print(x)
输出:
1
2
3
判断「在不在」:in(集合的看家本领)
s = {1, 2, 3}
print(2 in s)
print(9 in s)
print(9 not in s)
输出:
True
False
True
in 特别快?列表要从头一个一个比,集合能直接算出它该在的位置去看一眼。所以「一长串数据里反复判断某个东西在不在」时,先把它们装进集合,速度会差很多。数个数、找最大最小、求和
和列表一样,这些内置函数集合都能用:
s = {5, 1, 9}
print(len(s), max(s), min(s), sum(s))
输出:
3 9 1 15
六、四个集合运算(交集 &、并集 |、差集 -、对称差 ^)
集合最漂亮的用法,是「拿两个集合比一比」。四个符号,对应四种关系:
| 符号 | 名字 | 含义 | 生活里的样子 |
|---|---|---|---|
& | 交集 | 两边都有的 | 两个班都报名的同学 |
| | 并集 | 两边合起来全部(自动去重) | 两个班加起来的所有人 |
- | 差集 | 在左边、不在右边的 | 只在 A 班、没去 B 班的人 |
^ | 对称差 | 只出现在一边的(去掉共同部分) | 只在一个班出现过的人 |
a = {1, 2, 3}
b = {2, 3, 4}
print('交集:', a & b)
print('并集:', a | b)
print('差集 a-b:', a - b)
print('差集 b-a:', b - a)
print('对称差:', a ^ b)
输出:
交集: {2, 3}
并集: {1, 2, 3, 4}
差集 a-b: {1}
差集 b-a: {4}
对称差: {1, 4}
a - b 是「在 a 里但不在 b 里」,b - a 正好相反。写的时候先在心里念一遍「谁减谁」。换成人名,就是一道很常见的题:
class_a = {'小明', '小红', '小刚'}
class_b = {'小红', '小刚', '小美'}
print('两个班都有的:', sorted(class_a & class_b))
print('两个班全部的人:', sorted(class_a | class_b))
print('只在 A 班的:', sorted(class_a - class_b))
print('只在一个班的:', sorted(class_a ^ class_b))
输出:
两个班都有的: ['小刚', '小红']
两个班全部的人: ['小刚', '小明', '小红', '小美']
只在 A 班的: ['小明']
只在一个班的: ['小明', '小美']
再来看两份书单,想知道哪些书重复买了、哪些只买了一边:
list1 = {'西游记', '水浒传', '朝花夕拾'}
list2 = {'红楼梦', '西游记', '呐喊'}
print('重复买的:', sorted(list1 & list2))
print('只买了没重复的:', sorted(list1 ^ list2))
输出:
重复买的: ['西游记']
只买了没重复的: ['呐喊', '朝花夕拾', '水浒传', '红楼梦']
sorted() 排出来是按字符编码排的,不是按拼音,所以顺序看着可能有点怪,这不是错。课程思政|诚信与职业操守 · 交集是共识,差集是盲区
交集 & 挑出两边都有的,差集 - 挑出只在一侧的。别只顾着看交集里「我们都同意的那批人」,做工作更要盯紧差集:只出现在一边的记录,往往才是问题藏身的地方。团队做数据核对也是这样,两个人口径一对,能对上的先放一放,对不上的逐条查——差异不是麻烦,它是线索。
七、方法版(intersection / union / difference / issubset…)
同样四件事,换成方法写
四个运算符都有一个同名的方法:
a = {1, 2, 3}
print(a.intersection([2, 3, 4]))
print(a.union([4]))
print(a.difference([2]))
print(a.symmetric_difference([3, 4]))
输出:
{2, 3}
{1, 2, 3, 4}
{1, 3}
{1, 2, 4}
结果是 {2, 3}、{1, 2, 3, 4}、{1, 3}、{1, 2, 4},和用符号一模一样。
| 运算 | 符号写法 | 方法写法 |
|---|---|---|
| 交集 | a & b | a.intersection(b) |
| 并集 | a | b | a.union(b) |
| 差集 | a - b | a.difference(b) |
| 对称差 | a ^ b | a.symmetric_difference(b) |
{1, 2, 3} & [2, 3] 会报 TypeError,而 {1, 2, 3}.intersection([2, 3]) 是好的。数据本来就在列表里、又不想先转成集合时,用方法更省事。print({1, 2, 3} & [2, 3])
运行后会报错(逐字照抄解释器):
TypeError: unsupported operand type(s) for &: 'set' and 'list'
三个判断题
这三个返回的都是 True / False,用来问「集合之间是什么关系」。
a = {1, 2}
print(a.issubset({1, 2, 3})) # a 是它的子集吗(a 全在里面)
print({1, 2, 3}.issuperset(a)) # 它把 a 全包含了吗
print(a.isdisjoint({4, 5})) # 两边完全没有重复吗
输出:
True
True
True
子集也能用比较符号写,但这里有个大坑:
print({1, 2} <= {1, 2, 3}) # True:是子集
print({1, 2} < {1, 2}) # False:小于等于成立,但不「小于」
输出:
True
False
<= 不是「小于等于」,是「子集」;< 是「真子集」(少一个才算)。看到集合比较大小别想成数字,{1, 2} < {1, 2} 是 False 而不是 True,正是这个道理。AI 助手小贴士|四个集合运算符用「班级名单」一讲就懂。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:|、&、-、^ 四个集合运算符各是什么意思?用「1 班和 2 班名单」的例子各演示一遍,打印结果并解释
八、集合推导式
和列表推导式长得几乎一样,只是把方括号换成花括号。得到的结果是一个集合,所以天生去重。
print({x * x for x in range(1, 6)})
print(sorted({x for x in range(10) if x % 3 == 0}))
输出:
{1, 4, 9, 16, 25}
[0, 3, 6, 9]
把「每个元素的第一个字母」收集起来,重复的自动只留一个:
words = ['apple', 'banana', 'avocado']
print(sorted({w[0] for w in words}))
输出:
['a', 'b']
sorted() 排一下。自己调试时看到顺序变了,不是程序出错。{n % 10 for n in nums} 就是「所有数字的个位数有哪几种」。九、frozenset:不可变的集合
集合本身是可以改的,所以集合不能放进集合,也不能当字典的键。要这个能力,就用 frozenset——冻结版集合,建好之后一个都改不了。
fs = frozenset([1, 2, 3])
print(fs)
print(len(fs), 2 in fs)
print(sorted(fs))
输出:
frozenset({1, 2, 3})
3 True
[1, 2, 3]
想改它?方法和列表一样,直接没有:
fs = frozenset([1, 2])
fs.add(3)
运行后会报错(逐字照抄解释器):
AttributeError: 'frozenset' object has no attribute 'add'
换来的好处是:它能当字典的键,也能被放进别的集合里。
d = {frozenset([1, 2]): '一对'}
print(d[frozenset([1, 2])])
s = {frozenset([1]), frozenset([2])}
print(len(s))
输出:
一对
2
四个运算它全都能用(因为不需要改动自己):
print(sorted(frozenset([1, 2, 3]) & {2, 3, 4}))
输出:
[2, 3]
课程思政|工匠精神与严谨求实 · 该冻结的,就别让它变
普通集合自己能被改,所以放不进别的集合,也当不了字典的键;frozenset 是冻结版,建好之后一个元素都改不动,换来的是它能安全地当键、能被塞进别的集合。这也是一种做事方式:有些数据一旦定下来,就该锁死不让它变。成绩册、合同里的金额、统计口径,都该留一份「冻住」的,之后谁动了它,一查账就知道。
十、类型转换:四种容器怎么互转
到这儿,四种组合数据类型——列表、元组、字典、集合——就都学完了。实际写代码时经常要在它们之间来回转,靠的就是几个同名的转换函数。
| 函数 | 把一个东西变成 | 例子 |
|---|---|---|
list(x) | 列表 | list('abc') → ['a', 'b', 'c'] |
tuple(x) | 元组 | tuple([1, 2]) → (1, 2) |
set(x) | 集合(顺手去重) | set([1, 1, 2]) → {1, 2} |
dict(x) | 字典(元素要是键值对) | dict([('a', 1)]) → {'a': 1} |
str(x) | 字符串 | str(123) → '123' |
列表 / 元组 / 集合:三者随便转
lst = [3, 1, 2, 1]
print(set(lst)) # 去重
print(tuple(lst))
print(list(set(lst))) # 去过重的列表
输出:
{1, 2, 3}
(3, 1, 2, 1)
[1, 2, 3]
注意 list(set(...)) 出来后的顺序不保证——集合本身是无序的。要固定顺序,先 sorted() 一下:
lst = [3, 1, 2, 1]
print(sorted(set(lst)))
输出:
[1, 2, 3]
字典转成别的:直接转只会给「键」
d = {'a': 1, 'b': 2}
print(list(d)) # 键
print(list(d.keys())) # 还是键
print(list(d.values())) # 值
print(list(d.items())) # (键, 值) 对
输出:
['a', 'b']
['a', 'b']
[1, 2]
[('a', 1), ('b', 2)]
转回字典:每个元素必须是「键值对」
pairs = [('a', 1), ('b', 2)]
print(dict(pairs))
print(dict([['x', 9], ['y', 8]])) # 用列表写也行
输出:
{'a': 1, 'b': 2}
{'x': 9, 'y': 8}
如果元素不是「长度 2 的一对」,就会报错:
print(dict([1, 2, 3]))
运行后会报错(逐字照抄解释器):
TypeError: cannot convert dictionary update sequence element #0 to a sequence
字符串 ↔ 列表
print(list('abc'))
print(''.join(['a', 'b', 'c']))
print('1,2,3'.split(','))
输出:
['a', 'b', 'c']
abc
['1', '2', '3']
list(字符串) 会把它拆成一个个字符;反过来 ''.join(列表) 能把一堆字符串再拼回去(join 要求里面的元素都是字符串)。
| 我想…… | 怎么写 |
|---|---|
| 列表去重 | list(set(lst)) |
| 把元组变成能改的列表 | list(t) |
| 把列表锁成元组 | tuple(lst) |
| 取字典所有的键 | list(d) 或 list(d.keys()) |
| 取字典的键值对 | list(d.items()) |
| 把键值对列表变回字典 | dict(pairs) |
| 把字符串拆成列表 | list(s) 或 s.split(分隔符) |
| 把列表拼成字符串 | ''.join(lst) |
list(字典) 得到的是键,不是值、也不是键值对。十一、十个基础案例
1. 一份点单记录去重
nums = [8, 3, 8, 5, 3, 5]
print(sorted(set(nums)))
输出:
[3, 5, 8]
2. 去重,但保留第一次出现的顺序
orders = ['奶茶', '炸鸡', '奶茶', '可乐', '炸鸡']
print(list(dict.fromkeys(orders)))
输出:
['奶茶', '炸鸡', '可乐']
3. 一句备注里出现了哪些不重复的字
text = '半糖去冰半'
print(sorted(set(text)))
输出:
['冰', '半', '去', '糖']
4. 数一数有几个不同的字
text = '半糖去冰'
print(len(set(text)))
输出:
4
5. 判断两份歌单有没有重合
a = ['晴天', '稻香']
b = ['起风了', '告白气球']
print(set(a).isdisjoint(b))
print(bool(set(a) & set(b)))
输出:
True
False
6. 两份歌单都有的歌
a = ['晴天', '稻香', '起风了', '稻香']
b = ['起风了', '稻香', '七里香']
print(sorted(set(a) & set(b)))
输出:
['稻香', '起风了']
7. 只在其中一份里出现的歌
a = ['晴天', '稻香', '起风了']
b = ['起风了', '稻香', '七里香']
print(sorted(set(a) ^ set(b)))
输出:
['七里香', '晴天']
8. 检查甜度是不是合法选项
options = {'无糖', '三分糖', '七分糖'}
choice = '三分糖'
if choice in options:
print('你点了', choice)
else:
print('没有这个选项')
输出:
你点了 三分糖
9. 一单里有几种不同的口味
orders = ['奶茶', '咖啡', '奶茶', '可乐', '咖啡']
print('总杯数:', len(orders))
print('不同口味:', len(set(orders)))
输出:
总杯数: 5
不同口味: 3
10. 把盲盒编号排好序再输出
s = {5, 3, 9, 1}
print(sorted(s))
print(sorted(s, reverse=True))
输出:
[1, 3, 5, 9]
[9, 5, 3, 1]
十二、常见坑
坑 1:空集合写成 {}
这是集合的头号大坑。{} 是空字典,一调用集合方法就报 AttributeError。
s = set() # 正确:空集合
print(type(s))
输出:
<class 'set'>
坑 2:想用下标取元素
s = {1, 2, 3}
print(s[0])
运行后会报错(逐字照抄解释器):
TypeError: 'set' object is not subscriptable
集合无序,没有「第 0 个」。要按位置取,先转到列表:list(s)[0]——但那个「第 0 个」是谁并不确定,通常说明你该用列表。
坑 3:把列表塞进集合
s = {1, 2}
s.add([3, 4])
运行后会报错(逐字照抄解释器):
TypeError: unhashable type: 'list'
元素必须不可变。想放一组数,就用元组:s.add((3, 4))。
坑 4:以为集合会记住顺序
print(s) 出来的顺序不保证和你写进去的一致,同一个程序不同次运行也可能不一样。要固定顺序,一律先 sorted()。
s = {3, 1, 2}
print(sorted(s)) # 每次都一样
输出:
[1, 2, 3]
坑 5:用 remove 删不存在的元素
s = {1, 2, 3}
s.remove(99)
运行后会报错(逐字照抄解释器):
KeyError: 99
不确定在不在,改用 s.discard(99),它会安静地什么都不做。
坑 6:把 <= 当成「小于等于」
print({1, 2} <= {1, 2}) # True:是子集(等于也算)
print({1, 2} < {1, 2}) # False:不是真子集
输出:
True
False
集合之间的 <= / < / >= / > 全部是「子集 / 真子集 / 超集 / 真超集」,和数字比大小完全无关。
AI 助手小贴士|集合的价值在去重和比对,用应用题练。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:出 3 道集合应用题:统计一篇文章里不重复的字数、找出两份名单都出现的人、检查学号有没有重复。等我写完点评
十三、报错手册
下面这些报错都是真实运行出来的,照抄本机解释器的原文。看到眼熟的,直接对照处理。
用下标取集合的元素
s = {1, 2, 3}
print(s[0])
运行后会报错(逐字照抄解释器):
TypeError: 'set' object is not subscriptable
原因:集合无序,没有「第几个」。要按下标取,请改用列表。
删一个不存在的元素
s = {1, 2, 3}
s.remove(99)
运行后会报错(逐字照抄解释器):
KeyError: 99
原因:remove 要求元素必须在。不确定就用 discard。
把列表放进集合
s = {[1, 2], 3}
运行后会报错(逐字照抄解释器):
TypeError: unhashable type: 'list'
原因:列表会变,不能算「固定位置」(不可哈希)。改用元组 (1, 2)。
空集合写成 {},再调用 add
s = {}
s.add(1)
运行后会报错(逐字照抄解释器):
AttributeError: 'dict' object has no attribute 'add'
原因:{} 建出来的是空字典,字典没有 add。空集合要写 set()。
用符号做运算,但另一边是列表
print({1, 2, 3} & [2, 3])
运行后会报错(逐字照抄解释器):
TypeError: unsupported operand type(s) for &: 'set' and 'list'
原因:& 只认集合。要么把列表转成集合(set([2, 3])),要么改用方法 {1, 2, 3}.intersection([2, 3])。
两个集合相加
print({1} + {2})
运行后会报错(逐字照抄解释器):
TypeError: unsupported operand type(s) for +: 'set' and 'set'
原因:集合不支持 +。「合起来」要用并集 | 或 union()。
想给 frozenset 加元素
fs = frozenset([1, 2])
fs.add(3)
运行后会报错(逐字照抄解释器):
AttributeError: 'frozenset' object has no attribute 'add'
原因:frozenset 是冻结的,一个都改不了。它就是靠「不能改」才能当字典的键。
想给集合排序
s = {3, 1, 2}
s.sort()
运行后会报错(逐字照抄解释器):
AttributeError: 'set' object has no attribute 'sort'
原因:集合没有 sort(它本来就无序)。用内置函数 sorted(s) 得到一个新列表。
对空集合 pop
s = set()
s.pop()
运行后会报错(逐字照抄解释器):
KeyError: 'pop from an empty set'
原因:里面一个元素都没有,没得删。删之前先判空:if s:。
AI 助手小贴士|交、并、差这些概念用生活场景(名单比对)让 AI 直接写给你看,比文字定义直观。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:两个班的学生名单分别存在两个列表里,怎么用集合找出:两个班都有的人、只在 1 班的人、合在一起去重后的名单?写出代码并加中文注释
十四、随堂自测(12 题)
点击选项即可判分,选错的题会立刻展开解析。做完可以看到正确率和错题清单,也可以重新答题。
1想把一个列表里重复的元素去掉,最省事的一行是?
- A.
nums = list(set(nums)) - B.
nums = set(nums) + [] - C.
nums.remove(nums) - D.
nums = sorted(nums)
set() 把重复的吃掉,再用 list() 转回列表。B 那行会报错(集合不能加列表),D 只是排序,重复的还在。2下面哪一行创建的是一个空集合?
- A.
s = {} - B.
s = [] - C.
s = set() - D.
s = ()
set()。{} 是空字典(最容易踩的坑),[] 是空列表,() 是空元组。3s = {1, 2, 3},执行 print(s[0]) 会发生什么?
- A. 输出 1
- B. 报
TypeError: 'set' object is not subscriptable - C. 输出
{1} - D. 输出 None
list(s)。4下面哪个不能放进集合?
- A. 数字
10 - B. 字符串
'abc' - C. 元组
(1, 2) - D. 列表
[1, 2]
TypeError: unhashable type: 'list';想放一组数就用元组。5s = {1, 2, 3},想删掉 4、而且「没有这个元素时也不报错」,该用哪个?
- A.
s.remove(4) - B.
s.discard(4) - C.
s.pop(4) - D.
s.delete(4)
discard() 删不存在的元素时安静地什么都不做;remove() 会报 KeyError: 4。集合里也没有 delete 这个方法。6{1, 2, 3} & {2, 3, 4} 的结果是?
- A.
{1, 2, 3, 4} - B.
{1, 4} - C.
{2, 3} - D.
{1, 3}
& 是交集,取两边都有的元素,所以是 {2, 3}。取全部用并集 |。7{1, 2, 3} ^ {2, 3, 4} 的结果是?
- A.
{2, 3} - B.
{1} - C.
{1, 2, 3, 4} - D.
{1, 4}
^ 是对称差,取「只出现在一边」的元素:1 只在左边、4 只在右边,共同的 2、3 被去掉。8集合里 x in s 判断的是?
- A. 元素 x 在不在集合 s 里
- B. 下标 x 有没有越界
- C. 集合里有没有以 x 命名的键
- D. 集合是不是空的
in 就是问「这个元素在不在里面」。注意和字典不同——字典的 in 查的是键,集合查的就是元素本身。9{1, 2} <= {1, 2, 3} 的结果是?
- A. 报错,集合不能比较
- B. True,
<=在这里表示「是子集」 - C. False,因为 1 和 3 不相等
- D.
返回 {1, 2}
<= 是「子集」,< 是「真子集」。{1, 2} 的元素全在 {1, 2, 3} 里,所以是 True。10关于 frozenset,下面说法正确的是?
- A. 它和 set 完全一样,只是名字长一点
- B. 它可以
add但不能remove - C. 它不可变,所以能当字典的键、也能放进别的集合
- D. 它只能装数字
frozenset 是「冻结的集合」,建好就一个都改不了(调用 add 会报 AttributeError)。正因为不可变,它能当字典的键。11要把列表 [1, 1, 2, 3] 去重后变回列表,下面哪一句对?
- A.
list(set([1, 1, 2, 3])) - B.
set(list([1, 1, 2, 3])) - C.
list(tuple([1, 1, 2, 3])) - D.
set([1, 1, 2, 3]).list()
set() 去重,外面再套 list() 转回列表。注意转回来后的顺序不保证(集合本身无序);set 也没有 .list() 这种方法。12把字典 d 转成列表时,list(d) 得到的是?
- A. 所有的值
- B. 所有
(键, 值)对 - C. 报错,字典不能转列表
- D. 所有的键
list(d) 得到的是键的列表。要键值对用 list(d.items()),要值用 list(d.values())。这是最容易记混的一处。