2024 Python3.10 系统入门+进阶(九):封装解构和集合Set常用操作详解

目录

一、封装和解构

1.1 基本概念

示例代码1:

lax_coordinates = (33.9425, -118.408056)
print(lax_coordinates)
print(type(lax_coordinates))  # 什么类型? <class 'tuple'>
lax_coordinates2 = 33.9425, -118.408056
print(lax_coordinates2)
print(type(lax_coordinates2))  # 什么类型? <class 'tuple'>

Python 等式右侧出现逗号分隔的多值的时候,就会将这几个值封装到元组中,这种操作称为封装 packing 示例代码2:

lax_coordinates = (33.9425, -118.408056)
latitude, longitude = lax_coordinates  # 解构(拆包)
print(latitude)
print(longitude)

Python 中等式右侧是一个容器类型,左侧是逗号分隔的多个标识符,将右侧容器中数据的一个个和左侧标识符一一对应,这种操作称为解构 unpacking 从 Python3 开始,对解构做了很大的改进,现在用起来已经非常的方便快捷,封装和解构是非常方便的提取数据的方法,在 Python、JavaScript 等语言中应用极广。

解构也可以叫做拆包,拆包的特点是不用我们自己动手通过索引从序列中提取元素,这样就减少了出错的可能。拆包的目标可以是任何可迭代对象,包括不支持索引表示法([])的迭代器。拆包对可迭代对象的唯一要求是,一次只能产出一项,提供给接收端变量。不过也有例外,可以使用星号(*)捕获余下的项,后续会进行讲解。最明显的拆包形式是并行赋值(parallel assignment),即把可迭代对象中的项赋值给变量元组,如上面示例所示,本文后续描述通通使用 解构。

调用函数时在参数前面加上一个 *,利用的也是解构,示例代码:

print(divmod(20, 8))  # (2, 4)
t = (20, 8)
print(divmod(*t))  # (2, 4)
quotient, remainder = divmod(*t)
print(quotient)  # 2
print(remainder)  # 4
"""
上述代码还展示了解构的另一个用途:为函数返回多个值提供一种便于调用方使用的方式。
"""

利用解构还可以轻松对调两个变量的值,省掉中间的临时变量,示例代码:

# 交换数据
x = 4
y = 5
t = x
x = y
y = t
print(x, y)
# 封装和解构,交换
x = 10
y = 11
x, y = y, x
print(x, y)

1.2 简单解构

示例代码:

# 左右个数相同
a, b = 1, 2
print(a, b)
a, b = (1, 2)
print(a, b)
a, b = [1, 2]
print(a, b)
a, b = [10, 20]
print(a, b)
a, b = {10, 20}  # 非线性结构
print(a, b)
a, b = {'a': 10, 'b': 20}  # 非线性结构也可以解构
print(a, b)
[a, b] = (1, 2)
print(a, b)
[a, b] = 10, 20
print(a, b)
(a, b) = {30, 40}
print(a, b)

# 那么,左右个数不一致可以吗?不可以
a, b = (10, 20, 30)  # 会抛出异常: ValueError: too many values to unpack (expected 2)
print(a, b)

解构赋值的对象也可以是一个列表,不过用途不大。据我所知,只有一种情况用得到:一个数据库查询只返回一个记录(比如,SQL 语句中有 LIMIT 1 子句),利用解构确保只返回一个结果。

1.3 剩余变量解构

定义函数时可以使用 *args 捕获余下的任意数量的参数,这是 Python 的一个经典特性。Python3 把这一思想延伸到了并行赋值上。示例代码:

a, *rest, b = [1, 2, 3, 4, 5]
print(a, b)  # 1 5
print(type(rest), rest)  # <class 'list'> [2, 3, 4]

a, b, *rest = [1, 2]
print(a, b, rest)  # 1 2 []

a, *rest = [1, 2, 3, 4, 5]
print(a, rest)  # 1 [2, 3, 4, 5]
*rest, b = [1, 2, 3, 4, 5]
print(rest, b)  # [1, 2, 3, 4] 5

*rest = [1, 2, 3, 4, 5]  # SyntaxError: starred assignment target must be in a list or tuple
# print(rest)  # 内容是什么? 抛出异常 只有一个变量哪里来的剩余概念,何不直接定义一个变量接收

# SyntaxError: multiple starred expressions in assignment
a, *r1, *r2, b = [1, 2, 3, 4, 5]  # 抛出异常
"""
并行赋值时,* 前缀只能应用到一个变量上,不过可以是任何位置上的变量。
"""

a, *_, b = [1, 2, 3, 4, 5]
print(a, b, _)  # 1 5 [2, 3, 4]
# _是最后一个输出值,这里将把它覆盖
_, *b, _ = [1, 2, 3]
print(_)  # 第一个_是什么 3
print(b)  # 是什么 [2]
print(_)  # 第二个_是什么 3

_ 是合法的标识符,这里它没有什么可读性,它在这里的作用就是表示不关心这个变量的值,我不想要,有人把它称作 丢弃(Throwaway)变量。

1.4 嵌套解构

解构的对象可以嵌套,例如 (a, b, (c, d))。如果值的嵌套结构是相同的,则 Python 能正确处理。解构嵌套元组,获取经度:

metro_areas = [
    ('Tokyo', 'JP', 36.933, (35.689722, 139.691667)),
    ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
    ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
    ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
    ('São Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
]


def main():
    print(f'{"":15} | {"latitude":>9} | {"longitude":>9}')
    #  每个元组是一个四字段记录,最后一个字段是坐标对。
    #  把最后一个字段赋值给一个嵌套元组,解构坐标对。
    for name, _, _, (lat, lon) in metro_areas:
        if lon <= 0:
            print(f'{name:15} | {lat:9.4f} | {lon:9.4f}')


if __name__ == '__main__':
    main()

1.5 其他解构

示例代码:

# 1.函数,后面会详细介绍(在函数调用中可以多次使用 *)
def fun(a, b, c, d, *rest):
    return a, b, c, d, rest


# (1, 2, 3, 4, (5, 6))
print(fun(*[1, 2], 3, *range(4, 7)))

# 2.定义列表、元组或集合字面量时,也可以使用 *
x = [range(5)]
y = [*range(5)]
z = list(range(5))
print(x)  # [range(0, 5)]
print(y)  # [0, 1, 2, 3, 4]
print(z)  # [0, 1, 2, 3, 4]
print(*range(4), 4)  # 0 1 2 3 4
print([*range(4), 4])  # [0, 1, 2, 3, 4]
print({*range(4), 4, *(5, 6, 7)})  # {0, 1, 2, 3, 4, 5, 6, 7}

1.6 序列模式匹配(Python 3.10 最引人注目的新功能)

Python 3.10 引入了一个非常引人注目的新功能:结构模式匹配("PEP 634—Structural Pattern Matching: Specification"),也被称为序列模式匹配。这一功能大大增强了 Python 处理复杂数据结构的能力,使得代码更加简洁和易读。

1.6.1 结构模式匹配的核心概念

match 语句:类似于其他编程语言中的 switch 语句。通过 match 语句,Python 程序员可以对一个表达式进行模式匹配。

表面上看,match/case 与 C 语言中的 switch/case 语句很像,但这只是表象。 与 switch 相比,match 的一大改进是支持析构,这是一种高级拆包形式。析构对 Python 世界来说是一个新词,不过在支持模式匹配的语言(例如 Scala 和 Elixir)文档中经常出现。

模式:在 match 语句中,使用各种模式来匹配表达式的结构。模式可以是简单的字面量、变量绑定、或更加复杂的结构(例如元组、列表、字典等)。

match/case 上下文中,str、bytes 和 bytearray 实例不作为序列处理。match 把这些类型视为 原子 值,就像整数 987 整体被视为一个值,而不是数字序列。倘若把这三种类型视为序列,就可能会由于意外匹配而导致 bug。如果想把这些类型的对象视为序列,则要在 match 子句中转换。标准库中的以下类型与序列模式兼容:list、memoryview、array.array、tuple、range、collections.deque

case:每个 case 子句定义了一种可能的匹配模式。如果表达式与某个 case 匹配,则执行该 case 下的代码。假想的 Robot 类中的方法:

def handle_command(self, message):
	match message:case ['BEEPER', frequency, times]:  ❷
			self.beep(times, frequency)
		case ['NECK', angle]:  ❸
			self.rotate_neck(angle)
		case ['LED', ident, intensity]:  ❹
			self.leds[ident].set_brightness(ident, intensity)
		case ['LED', ident, red, green, blue]:  ❺
			self.leds[ident].set_color(ident, red, green, blue)
		case _:raise InvalidCommand(message)match 关键字后面的表达式是匹配对象(subject),即各个case子句中的模式尝试匹配的数据。
② 这个模式匹配一个含有3项的序列。第一项必须是字符串'BEEPER'。第二项和第三项任意,依次绑定到变量frequency和times上。
③ 这个模式匹配任何含有两项,而且第一项为 'NECK' 的序列。
④ 这个模式匹配第一项为 'LED',共有 3 项的序列。如果项数不匹配,则 Python 继续执行下一个 case 子句。
⑤ 这个模式也匹配第一项为 'LED' 的序列,不过一共有 5 项。
⑥ 这是默认的 case 子句,前面所有模式都不匹配时执行。_ 是特殊的变量,稍后讲解。
匹配相应位置上的任何一项,但不绑定匹配项的值。另外,_ 是唯一可在模式中多次出现的变量。
⑦ 模式中的任何一部分均可使用 as 关键字绑定到变量上。

析构嵌套元组(要求 Python 3.10 及以上版本),示例代码:

metro_areas = [
    ('Tokyo', 'JP', 36.933, (35.689722, 139.691667)),
    ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
    ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
    ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
    ('São Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
]


def main():
    print(f'{"":15} | {"latitude":>9} | {"longitude":>9}')
    for record in metro_areas:
        # 这个 match 的匹配对象是 record,即 metro_areas 中的各个元组。
        match record:
            # 一个 case 子句由两部分组成:一部分是模式,另一部分是使用 if 关键字指定的卫语句(guard clause,可选)。
            case [name, _, _, (lat, lon)] if lon <= 0:
                """
                一般来说,匹配对象同时满足以下条件方能匹配序列模式。
                    ① 匹配对象是序列。
                    ② 匹配对象和模式的项数相等。
                    ③ 对应的项相互匹配,包括嵌套的项。
                """
                print(f'{name:15} | {lat:9.4f} | {lon:9.4f}')


if __name__ == '__main__':
    main()

上述代码中的模式 [name, _, _, (lat, lon)] 匹配一个含有 4 项的序列,而且最后一项必须是一个含有两项的序列。序列模式可以写成元组或列表,或者任意形式的嵌套元组和列表,使用哪种句法都没有区别,因为在序列模式中,方括号和圆括号的意思是一样的。示例中的模式写成列表形式,其中嵌套的序列则写成元组形式,这样做只是为了避免重复使用方括号或圆括号。

模式中的任何一部分均可使用 as 关键字绑定到变量上。示例:

case [name, _, _, (lat, lon) as coord]:
上述模式可以匹配 ['Shanghai', 'CN', 24.9, (31.1, 121.3)],并设定以下变量。
name    'Shanghai'
lat     31.1
lon     121.3
coord  (31.1, 121.3)

添加类型信息可以让模式更具体。例如,下面的模式与前面的示例匹配相同的嵌套序列结构,不过第一项必须是 str 实例,而且二元组中的两项必须是 float 实例。

case [str(name), _, _, (float(lat), float(lon))]:

str(name) 和 float(lat) 看起来像是构造函数调用——前者把 name 转换成 str,后者把 lat 转换成 float。其实不然,在模式上下文中,这种句法的作用是在运行时检查类型。前面的模式将匹配一个 4 项序列,其中第一项必须是一个字符串,第四项必须是一对浮点数。而且,第一项中的字符串将绑定到 name 变量上,第四项中的一对浮点数将分别绑定到 lat 和 lon 两个变量上。因此,尽管 str(name) 借用了构造函数调用句法,但是在模式上下文中,语义是完全不同的。此外,如果想要匹配任何以字符串开头、以嵌套两个浮点数的序列结尾的序列,则可以使用如下模式。

case [str(name), *_, (float(lat), float(lon))]:

*_ 匹配任意数量的项,而且不绑定变量。如果把 *_ 换成 *extra,匹配的零项或多项将作为列表绑定到 extra 变量上。以 if 开头的卫语句是可选的,仅当匹配模式时才运行。

match record:
   case [name, _, _, (lat, lon)] if lon <= 0:
   	   # 嵌套块中的 print 语句仅当匹配模式且卫语句为真时才运行。
       print(f'{name:15} | {lat:9.4f} | {lon:9.4f}')

1.6.2 结构模式匹配的优势

  1. 简化代码逻辑:不需要多层嵌套的 if-elif 语句,代码更加直观。
  2. 提高可读性:通过模式匹配,代码的意图更加明确,容易理解。
  3. 灵活性:支持嵌套模式和复杂数据结构的匹配,适用于各种情况。

1.6.3 使用场景

  1. 解析和处理复杂的嵌套数据结构(如 JSON/AST 树等)。
  2. 替代传统的 if-elif 语句,用于处理不同类型的数据。
  3. 构建解析器或解释器。

二、集合Set

Python 中的集合同数学中的集合概念类似,也是用于保存不重复元素的。它有 可变集合(set)不可变集合(frozenset) 两种。本文所要介绍的可变集合是无序可变序列,而不可变集合在本文中不做介绍。在形式上,集合的所有元素都放在一对 {...} 中,两个相邻元素间使用 , 分隔。集合最好的应用就是去掉重复元素,因为集合中的每个元素都是唯一的。

说明:在数学中,集合的定义是把一些能够确定的不同的对象看成一个整体,而这个整体就是由这些对象的全体构成的集合。集合通常用 {...} 或者大写的拉丁字母表示。

集合的特点:

  1. 无序的数据结构。集合内的数据随机排列。
  2. 可变的数据类型。可以随意读写集合内的数据。
  3. 不能够直接映射或索引内部数据。但可以迭代或检查数据。
  4. 内部数据统称为元素,每个元素必须是唯一的、不可变的。因此集合是一组无序排列的可哈希的值。元素可以是数字、字符串或者元组,但不能使用列表、字典、集合等可变类型数据。
  5. 集合的字面值使用大括号包含所有元素,元素之间使用逗号分隔。注意:空 set 没有字面量表示法,必须写作 set()。倘若写成 {},则创建的是空 dict。

2.1 初始化

2.1.1 “{}”–直接创建集合

在 Python 中,创建 set 集合也可以像列表、元组一样,直接将集合赋值给变量从而实现创建集合,即直接使用大括号 {} 创建。语法格式如下:

setname = {element 1,element 2,element 3,,element n}

参数说明:

  1. setname:表示集合名称,可以是任何符合 Python 命名规则的标识符;
  2. element 1、element 2、element 3、elemnet n:表示集合中的元素,个数没有限制,并且只要是 Python 支持的不可变数据类型(如字符串、数字、元组及布尔类型的 True 或者 False 等,但不能是列表、字典、集合等)就可以。

注意: 在创建集合时,如果输入了重复的元素,Python 会自动只保留一个。

【示例1】直接创建集合并输出。

# 直接创建集合并输出
set1 = {1, 3, 5, 7, 9}  # 创建10以内奇数的集合
print('set1:', set1)
set2 = {'A', 'B', 'C', 'D', 'E'}  # 部分大写英文字母的集合
print('set2:', set2)
# 手机品牌名称字符的集合
set3 = {'华为', 'apple', 'OPPO', '小米'}
print('set3:', set3)
set4 = {'Python', 28, ('人生苦短', '我用Python'), True}  # 不同类型数据的集合
print('set4:', set4)
# 保存学生信息元组的集合
set5 = {('1001', '无语', 98, 100, 96), ('1002', '琦琦', 100, 96, 97)}
print('set5:', set5)

【示例2】演示通过列表、字典等可变对象作为集合元素,抛出异常。

# 集合中的元素,不能是列表、字典、集合等可变对象
set1 = {88, [75, 66.5], 62}  # 提示TypeError: unhashable type: 'list'
set2 = {1, {"one": 1}, 2}  # 提示TypeError: unhashable type: 'dict'
set3 = {1, {1, 2}}  # TypeError: unhashable type: 'set'
set4 = {bytearray([65, 66, 67]), 1}  # TypeError: unhashable type: 'bytearray'

【示例3】通过集合推导式生成集合。

import random

# 通过集合推导式生成集合
set1 = {i for i in range(10)}  # 创建0~10之间(不包括10)的数字集合
print(set1)
set2 = {i for i in range(2, 10, 2)}  # 创建10以内(不包括10)的偶数集合
print(set2)
# 创建无重复的4位随机数集合
set3 = {random.randint(1000, 10000) for i in range(10)}
print(set3)
set4 = {i for i in '壹贰叁肆伍'}  # 将字符串转换为集合
print(set4)
# 生成所有单词首字母集合
set5 = {i[0] for i in ['Early', 'bird', 'gets', 'the', 'worm']}
print(set5)
# 将原集合中的数字折半后生成新的集合
set6 = {int(i * 0.5) for i in {1200, 5608, 4314, 6060, 5210}}
print(set6)
set7 = {i for i in ('Early', 'bird', 'gets', 'the', 'worm')}  # 通过元组生成新的集合
print(set7)
# 将字典的Key生成新的集合
set8 = {key for key in {'name': 'amo', 'age': 18, 'address': '重庆市'}}
print(set8)
# 将字典的Value生成新的集合
set9 = {v for k, v in {'name': 'amo', 'age': 18, 'address': '重庆市'}.items()}
print(set9)

2.1.2 set()函数–将可迭代对象转换为可变集合

set() 函数用于将可迭代对象转换为一个无序不重复元素的可变集合,返回的集合是可以修改的,我们可以对集合元素进行添加或删除等,还可以进行交集、并集、差集等操作,其语法格式如下:

In [20]: set?
Init signature: set(self, /, *args, **kwargs)
Docstring:
set() -> new empty set object
set(iterable) -> new set object

Build an unordered collection of unique elements.
Type:           type
Subclasses:
参数说明: 
1.iterable:表示要转换为集合的可迭代对象,可以是列表、元组、range对象、字符串等
2.返回值:返回一个新的集合对象;当不传入参数时,生成一个新的空集合

示例:

# 根据传入的参数创建一个新的集合
print(set())  # 不传入参数,创建空集合 set()
# {'H', 'p', 'a', 'y'}
print(set('Happy'))  # 将字符串转换为集合,返回不重复字符的集合,重复的被删除
# {'人生苦短', '我用Python'}
print(set(('人生苦短', '我用Python')))  # 将元组转换为集合
# 在Python中集合是无序的,每次输出集合的元素时,元素的排列顺序也不同,且与运行环境相关。
# {'Forever', 'Alone', 'Hello', 'I Need You'}
print(set(['Forever', 'I Need You', 'Alone', 'Hello']))  # 将列表转换为集合
print(set([88, 100, 67, 88, 88, 67]))  # 将列表转换为集合,重复的被删除 {88, 67, 100}
print(set(range(10)))  # 将range对象转换为集合 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
print(set({1, 3, 5, 7, 9}))
# 如果是字典对象,将会使用字典对象的键作为集合的值
print(set({'name': 'amo', 'age': 18}))

2.2 访问集合

集合对象是一组无序排列的可哈希的值,因此集合元素可以作为字典的键,集合相当于字典的键集。因此使用 in 和 not in 运算符可以检查元素,使用 len() 函数获取集合长度(元素个数),使用 for 循环可以迭代集合的元素。示例:

set1 = {'a', 'b', 'c'}  # 定义集合
for i in set1:
    print(i)
# print(set1[0]) # TypeError: 'set' object is not subscriptable

只要是容器,都可以遍历元素。但是效率都是 O(n) 集合本身是无序的,不可以为集合创建索引,或执行切片操作,也没有键可用来映射集合中的元素,因此无法直接访问特定元素的值,如果要访问集合元素,可以先把集合转换为列表或元组,然后通过下标进行访问,示例:

set1 = {'a', 'b', 'c'}
list1 = list(set1)
print(list1[0])  # 通过这种方式获取的元素值是随机的,每次取值未必相同,与运行环境相关

2.3 集合的添加和删除

2.3.1 add()方法–向集合中添加元素

集合中的 add() 方法用于向集合中添加元素,如果添加的元素在集合中已存在,则不执行任何操作。其语法格式如下:

In [21]: set.add?
Docstring:
Add an element to a set.

This has no effect if the element is already present.
Type:      method_descriptor
set.add(element)

参数说明:
1.set:表示要添加元素的集合。
2.element:表示要添加的元素内容,只能使用字符串、数字、元组及布尔类型的True或者False等不可变对象,
但不能使用列表、字典等可变对象。

示例代码:

# 1.将指定元素添加到集合当中
university = {"麻省理工学院", "斯坦福大学", "哈佛大学", "加州理工学院"}
print("添加元素前:", university)
university.add("牛津大学")  # 添加一个元素
print("添加元素后:", university)
# 2.向集合中添加已经存在的元素
language_set = {'Python', 'C', 'C++', 'Java', 'PHP'}  # 集合数据
print('添加元素前:', language_set)
language_set.add('Python')  # 向集合中添加已经存在的元素
print('添加已存在元素后:', language_set)
s = set(range(2, 10))  # 使用set()函数创建集合
print("添加元素前:", s)
s.add(10)  # 添加数字元素
s.add((11, 12, 13, 15))  # 添加元组元素
s.add("num")  # 添加字符串元素
s.add(True)  # 添加True
print("添加元素后:", s)
# s.add([1, 2, 3, 4]) TypeError: unhashable type: 'list'

2.3.2 update()方法–更新原集合为两个集合的并集

集合中的 update() 方法用于更新原集合为两个集合的并集,即将 集合a集合b 取并集,并将结果更新到(添加到)集合a 中,但不改变 集合b,该方法无返回值。其语法格式如下:

set_a.update(set_b)
参数说明: 
1.set_a:表示需要更新的集合a。
2.set_b:集合b,可以是集合或其他的可迭代对象(如列表、元组、字典等),可以是一个或多个可迭代对象,多个可迭代对象之间
用逗号隔开。
3.返回值:None4.提示:如果添加的元素在原集合中已存在,则该元素只会出现一次,重复的会被忽略。

示例代码:

# 更新当前集合
surname1 = set("赵钱孙李")  # 将字符串转换为集合
surname2 = set("周吴郑王")  # 将字符串转换为集合
print("更新前的集合", surname1)
surname1.update(surname2)  # 参数为集合
surname1.update("冯陈")  # 参数为字符串
surname1.update(("楮", "卫"))  # 参数为元组
# update()方法的参数不能为数字,否则将提示TypeError: 'int' object is not iterable
# surname1.update(1)
print("更新后的集合", surname1)
# 将多个可迭代对象同时更新到集合中
num1 = set(range(1, 10, 2))  # 将range对象转换为集合
num2 = (2, 11, 20, 9)  # 创建元组
num3 = [50, 100]  # 创建列表
num4 = {"0001": "Tom", "0002": "Jony"}  # 创建字典
print("更新前的集合num1:", num1)
# 将元组num2、列表num3、字典num4添加到集合num1中
# 提示:字典类型作用的是key
num1.update(num2, num3, num4)  # 参数为多个对象
print("更新后的集合num1:", num1)

2.3.3 remove()方法–删除集合中的指定元素

集合 remove() 方法用于从集合中删除指定元素,如果要删除的指定元素不存在,将抛出 KeyError 异常。其语法格式如下:

set.remove(element)
参数说明: 
1.set: 表示要删除指定元素的集合
2.element: 集合中指定要删除的元素

示例代码:

# 从集合中删除指定元素
poem = {"少年易老学难成", "一寸光阴不可轻", "未觉池塘春草梦", "阶前梧叶已秋声"}  # 创建集合
print("删除前", poem)
poem.remove("未觉池塘春草梦")  # 删除集合中的指定元素
poem.remove("阶前梧叶已秋声")
print("删除后", poem)
poem = {"少年易老学难成", "一寸光阴不可轻"}  # 创建字典

# 指定的内容不存在,将抛出KeyError异常
# poem.remove("未觉池塘春草梦")  # 提示KeyError: '未觉池塘春草梦'

# 通过for循环删除集合中不是中文的字符元素
idiom_set = {"王侯将相", "相忍为国", "国富民强", "强作解人", "1234", "rmwq"}  # 字符串类型数据的集合
for i in list(idiom_set):  # 循环遍历元素
    if not '\u4e00' <= i <= '\u9fff':  # 判断元素是否为中文
        idiom_set.remove(i)  # 删除不是中文的元素
print("删除元素后的集合为:", idiom_set)  # 打印删除元素后的集合

2.3.4 discard()方法–删除集合中的指定元素

集合中的 discard() 方法用于删除集合中的指定元素。如果要删除的指定元素不存在,不会报错。其语法格式如下:

set.discard(element)
参数说明: 
1.set:表示要删除指定元素的集合
2.element:集合中指定要删除的元素

示例代码:

# 删除集合中的指定元素
language = {"Java", "C", "C++", "Python"}  # 创建集合
print("删除指定元素前:", language)
language.discard("Java")  # 删除"Java"元素
print("删除指定元素后:", language)
# discard()方法与remove()方法的区别
s = {"Java", "C", "Python"}  # 创建集合
# s.remove("PHP")  # remove()方法会抛出KeyError异常,提示KeyError: 'PHP'
s.discard("PHP")  # discard()方法不会报错

2.3.5 pop()方法–随机删除集合中的一个元素并返回该元素

集合中的 pop() 方法用于随机删除集合中的一个元素并返回该元素。其语法格式如下:

set.pop()
参数说明: 
1.set:表示集合对象
2.返回值:返回随机删除的元素

示例代码:

# 随机删除集合中的一个元素
digital = {"手机", "平板电脑", "数码相机", "摄像机", "耳机"}  # 创建集合
print("删除前:", digital)
print("随机删除的元素为:", digital.pop())  # 随机删除集合中的元素并返回
print("随机删除的元素为:", digital.pop())
print("删除后:", digital)
# 注意:如果集合为空,却调用了pop()方法,会抛出KeyError异常。
set().pop()  # KeyError: 'pop from an empty set'

2.3.6 clear()方法–删除集合中的全部元素

集合中的 clear() 方法用于删除集合中的全部元素,使其变为空集合。其语法格式如下:

set.clear()
参数说明: 
1.set: 表示要删除全部元素的集合。

示例代码:

# 删除集合中的全部元素
song = set(['Forever', 'I Need You', 'Hello'])  # 使用set()函数将列表转换为集合
print("清空元素前:", song)  # 清空元素前: {'Forever', 'I Need You', 'Hello'}
song.clear()  # 清空集合
print("清空元素后:", song)  # 空集合 清空元素后: set()
'''
我们可以使用del set命令删除整个集合。但del语句在实际开发时,并不常用。
因为Python自带的垃圾回收机制会自动销毁不用的集合,所以即使我们不手动将其删除,Python也会自动将其回收。
'''

2.4 集合的交集、并集和差集运算

2.4.1 集合概念

2.4.1.1 全集

全集(Universal Set) 是集合论中的一个基本概念。它指的是在某个特定讨论范围或背景下包含所有可能考虑的元素的集合。全集通常用符号 U 表示。

特点:

  1. 包含性:在特定讨论范围内,所有其他集合都是全集的子集。也就是说,任意一个集合中的元素都在全集中。
  2. 背景依赖:全集的定义是相对的,依赖于当前讨论的问题背景。例如,在讨论所有自然数时,全集可以是所有自然数的集合;在讨论学生时,全集可以是该班级或学校的所有学生集合。

例子:

  1. 例子 1:如果我们讨论集合 A = {1, 2} 和 B = {2, 3},则一个可能的全集可以是 U = {1, 2, 3, 4},因为 A 和 B 的所有元素都包含在 U 中。
  2. 例子 2:在字母集合 A = {'a', 'b'}B = {'b', 'c'} 的背景下,全集可以是 U = {'a', 'b', 'c', 'd', ..., 'z'},即所有小写字母的集合。

全集与补集的关系:对于任意集合 A,其补集 A' 是 U 中不属于 A 的所有元素的集合。补集的定义依赖于全集的选择。如果 U = {1, 2, 3, 4},A = {1, 2},则 A' = {3, 4}。

使用场景:

  1. 数学运算:全集在定义补集、差集等运算时非常重要。
  2. 逻辑推理:在逻辑和集合运算中,全集帮助确定讨论的范围。

总之,全集定义了讨论范围内所有可能元素的边界,任何在该背景下讨论的集合都应视为全集的子集。

2.4.1.2 子集

子集(Subset) 是集合论中的一个重要概念。一个集合 A 是另一个集合 B 的子集,表示 A 中的每一个元素都属于 B。我们用符号 A ⊆ B 来表示这种包含关系。

子集的定义:形式化定义:集合 A 是集合 B 的子集,记作 A ⊆ B,如果对于 A 中的每一个元素 x,x 都是 B 的元素。这可以用公式表示为:
在这里插入图片描述
真子集(Proper Subset): 如果 A 是 B 的子集,并且 A 不等于 B,则 A 被称为 B 的真子集,记作 A ⊂ B。这意味着 B 至少有一个元素不在 A 中。例子:如果 A = {1, 2} 和 B = {1, 2, 3},那么 A ⊂ B。

特殊情况: 空集:空集 ∅ 是任何集合的子集,包括它自身。即对于任意集合 B,都有 ∅ ⊆ B。例子:如果 B = {1, 2, 3},则 ∅ ⊆ B。自身子集: 任何集合 A 都是它自身的子集,A ⊆ A。

子集的例子:

  1. 例子 1:设 A = {1, 2} 和 B = {1, 2, 3, 4}。因为 A 中的元素 1 和 2 也都在 B 中,所以 A ⊆ B。
  2. 例子 2:设 C = {a, b, c} 和 D = {a, b, c, d}。因为 C 是 D 的子集,但 C 与 D 不相等,所以 C ⊂ D。

子集运算:

  1. 并集的子集:若 A ⊆ B,则 A 与任意集合的并集也应是 B 的子集。即 A ∪ C ⊆ B ∪ C。
  2. 交集的子集:若 A ⊆ B,则 A 与任意集合的交集也是 B 的子集。即 A ∩ C ⊆ B ∩ C。

幂集(Power Set): 一个集合 A 的幂集是 A 的所有子集的集合,记作 P(A)。例子:如果 A = {1, 2},则 P(A) = {∅, {1}, {2}, {1, 2}}。

总结来说,子集是集合论中一个基础而重要的概念,广泛应用于数学、计算机科学等领域,用于描述集合之间的包含关系。

2.4.1.3 超集

超集(Superset) 是集合论中的一个概念,与子集相对。一个集合 B 是另一个集合 A 的超集,表示 B 中的每一个元素都包括 A 的所有元素。我们用符号 B ⊇ A 来表示这种关系。

超集的定义:集合 B 是集合 A 的超集,记作 B ⊇ A,如果对于 A 中的每一个元素 x,x 也属于 B。这可以用公式表示为:
在这里插入图片描述
也就是说,如果 A ⊆ B,则 B 是 A 的超集。

真超集(Proper Superset): 如果 B 是 A 的超集,并且 B 不等于 A,则 B 被称为 A 的真超集,记作 B ⊃ A。这意味着 B 至少有一个元素不在 A 中。例子:如果 A = {1, 2} 和 B = {1, 2, 3},那么 B ⊃ A。

特殊情况:全集:在某个特定讨论范围内,全集 U 是所有集合的超集。例子:在所有自然数的集合 N 中,N 是任意自然数子集的超集。自身超集: 任何集合 A 都是它自身的超集,A ⊇ A。

超集的例子:

  1. 例子 1:设 A = {1, 2} 和 B = {1, 2, 3, 4}。因为 B 包含 A 的所有元素,所以 B ⊇ A。
  2. 例子 2:设 C = {a, b, c} 和 D = {a, b, c, d}。因为 D 是 C 的真超集,所以 D ⊃ C。

超集与子集的关系: 反向关系:如果 A ⊆ B,那么 B ⊇ A。换句话说,A 是 B 的子集当且仅当 B 是 A 的超集。

使用场景:

  1. 集合包含性判断:在数学、逻辑、数据库查询等领域,经常使用超集来判断某集合是否完全包含另一集合。
  2. 优化与简化:在算法设计中,超集概念可以帮助优化搜索空间。例如,通过超集的识别,可以减少不必要的计算。

具体例子:例子 3:假设 A = {1, 2, 3},那么 A 是 {1, 2}、{1} 和 ∅ 的超集,记作 A ⊇ {1, 2}、A ⊇ {1} 和 A ⊇ ∅。总之,超集是集合论中一个基本而重要的概念,用于描述一个集合是否包含另一个集合的所有元素,与子集概念密切相关。

2.4.1.4 并集

并集(Union) 是集合论中的一个基本运算。两个集合的并集包含所有属于这两个集合的元素,不重复。并集是用来合并两个或多个集合中的所有元素的操作。

并集的定义:形式化定义:集合 A 和 B 的并集是包含所有属于 A 或 B 的元素的集合,记作 A ∪ B。
在这里插入图片描述
换句话说,A ∪ B 包含所有属于 A 的元素、所有属于 B 的元素,以及同时属于 A 和 B 的元素。

并集的例子:

  1. 例子 1:如果 A = {1, 2, 3} 和 B = {3, 4, 5},则 A ∪ B = {1, 2, 3, 4, 5}。在这个例子中,3 是 A 和 B 的公共元素,但在并集中只出现一次。
  2. 例子 2:如果 C = {'a', 'b'} 和 D = {'b', 'c', 'd'},则 C ∪ D = {'a', 'b', 'c', 'd'}

并集的性质:

  1. 交换性:A ∪ B = B ∪ A。即并集的顺序不影响结果。例子:{1, 2} ∪ {2, 3} = {2, 3} ∪ {1, 2}。
  2. 结合性:(A ∪ B) ∪ C = A ∪ (B ∪ C)。即多集合的并集可以按任意顺序进行。例子:({1} ∪ {2}) ∪ {3} = {1} ∪ ({2} ∪ {3})。
  3. 幂等性:A ∪ A = A。一个集合与自身的并集仍然是它本身。例子:{1, 2} ∪ {1, 2} = {1, 2}。
  4. 空集:对于任意集合 A,A ∪ ∅ = A。例子:{1, 2} ∪ ∅ = {1, 2}。
  5. 全集:如果 U 是一个全集,A 是 U 的子集,那么 A ∪ U = U。例子:如果 U = {1, 2, 3, 4} 且 A = {1, 2},则 A ∪ U = {1, 2, 3, 4}。

应用场景:

  1. 数据合并:在数据库操作、集合分析、逻辑推理等领域,并集操作用于合并多个数据集或条件集合。
  2. 图形理论:在图形理论中,并集操作用于合并多个子图的顶点或边。

具体场景的扩展: 多个集合的并集:对于多个集合 A1, A2, ..., An 的并集,记作 A1 ∪ A2 ∪ … ∪ An,其结果是包含所有这些集合中的元素的集合。并集与交集的结合: 并集和交集经常一起使用,以分析集合的整体结构。例如,(A ∪ B) ∩ C 表示 A 和 B 的并集与 C 的交集。总结来说,并集是集合论中用来合并集合元素的基本操作,它包含所有属于任意一个参与集合的元素,并且每个元素在结果集中只出现一次。

2.4.1.5 交集

交集(Intersection) 是集合论中的一个基本运算。两个集合的交集包含所有同时属于这两个集合的元素,表示两个集合的重叠部分。

交集的定义:形式化定义:集合 A 和 B 的交集是由所有既属于 A 又属于 B 的元素组成的集合,记作 A ∩ B。
在这里插入图片描述
换句话说,A ∩ B 包含所有同时属于 A 和 B 的元素。

交集的例子:

  1. 例子 1:如果 A = {1, 2, 3} 和 B = {3, 4, 5},则 A ∩ B = {3}。在这个例子中,只有 3 同时属于 A 和 B。
  2. 例子 2:如果 C = {'a', 'b', 'c'} 和 D = {'b', 'c', 'd'},则 C ∩ D = {'b', 'c'}。在这里,b 和 c 同时属于 C 和 D。

交集的性质:

  1. 交换性:A ∩ B = B ∩ A。即交集的顺序不影响结果。例子:{1, 2} ∩ {2, 3} = {2, 3} ∩ {1, 2}。
  2. 结合性:(A ∩ B) ∩ C = A ∩ (B ∩ C)。即多集合的交集可以按任意顺序进行。例子:({1} ∩ {2}) ∩ {3} = {1} ∩ ({2} ∩ {3})。
  3. 幂等性:A ∩ A = A。一个集合与自身的交集仍然是它本身。例子:{1, 2} ∩ {1, 2} = {1, 2}。
  4. 空集:对于任意集合 A,A ∩ ∅ = ∅。例子:{1, 2} ∩ ∅ = ∅。
  5. 包含关系:如果 A ⊆ B,那么 A ∩ B = A。例子:如果 A = {1, 2} 且 B = {1, 2, 3},则 A ∩ B = {1, 2}。

应用场景:

  1. 数据过滤:在数据库查询、数据分析等领域,交集用于提取同时满足多个条件的数据。
  2. 逻辑运算:在逻辑学中,交集对应于逻辑运算中的 与(AND) 操作,用于找出多个条件同时成立的情况。
  3. 图形理论:在图形理论中,交集可以用来找出两个图中共有的顶点或边。

具体场景的扩展: 多个集合的交集:对于多个集合 A1, A2, …, An 的交集,记作 A1 ∩ A2 ∩ … ∩ An,其结果是同时属于所有这些集合的元素。交集与并集的结合: 交集和并集可以一起使用来分析集合的复杂关系。例如,(A ∩ B) ∪ C 表示 A 和 B 的交集再与 C 的并集。可视化理解: 在维恩图中,交集通常表示为两个或多个圆形的重叠部分,代表共同的元素。总之,交集是集合论中用于找出共同元素的基本操作,它只包含同时属于所有参与集合的元素。

2.4.1.6 差集

差集(Difference) 是集合论中的一个基本运算,用来表示一个集合中属于该集合但不属于另一个集合的元素。差集描述了两个集合之间的“差异”部分。

差集的定义:形式化定义:集合 A 和 B 的差集是包含所有属于 A 但不属于 B 的元素的集合,记作 A - B 或 A \ B。
在这里插入图片描述
换句话说,A - B 包含所有在 A 中但不在 B 中的元素。

差集的例子:

  1. 例子 1:如果 A = {1, 2, 3, 4} 和 B = {3, 4, 5, 6},则 A - B = {1, 2}。在这个例子中,只有 1 和 2 属于 A 且不属于 B。
  2. 例子 2:如果 C = {'a', 'b', 'c'} 和 D = {'b', 'c', 'd'},则 C - D = {'a'}。这里,a 属于 C 但不属于 D。

差集的性质:

  1. 非交换性:A - B 和 B - A 不一定相等。一般来说,A - B ≠ B - A。例子:如果 A = {1, 2} 和 B = {2, 3},则 A - B = {1} 而 B - A = {3}。
  2. 差集与空集:对于任意集合 A,A - ∅ = A 和 A - A = ∅。例子:如果 A = {1, 2, 3},则 A - ∅ = {1, 2, 3} 和 A - A = ∅。
  3. 包含关系:如果 A ⊆ B,则 A - B = ∅。例子:如果 A = {1, 2} 且 B = {1, 2, 3},则 A - B = ∅。
  4. 结合性:差集运算不具有结合性,即 (A - B) - C ≠ A - (B - C)。例子:假设 A = {1, 2, 3},B = {2, 3},C = {3},则 (A - B) - C = ∅ 和 A - (B - C) = {1}。

应用场景:

  1. 数据筛选:在数据处理、数据库查询等领域,差集用于筛选出只存在于一个数据集但不在另一个数据集中的元素。
  2. 逻辑运算:差集对应于逻辑运算中的 非(NOT) 操作,用于排除某些条件。
  3. 图形理论:在图形理论中,差集可以用于找出一个图中有但另一个图中没有的边或顶点。

具体场景的扩展:对称差集(Symmetric Difference): 对称差集是指两个集合的差集的并集,记作 A Δ B,即 (A - B) ∪ (B - A)。对称差集包含那些仅在 A 或 B 中出现但不在两者共同出现的元素。例子:A = {1, 2, 3} 和 B = {3, 4},则 A Δ B = {1, 2, 4}。

可视化理解:在维恩图中,差集通常表示为两个圆形中属于一个圆但不属于另一个圆的部分。总之,差集是集合论中的一种操作,用来找出一个集合中属于该集合但不属于另一个集合的元素。差集在各种数据分析和逻辑运算中有广泛应用。

2.4.2 Python方法实现

2.4.2.1 “&”、intersection()方法、intersection_update()方法 -------交集

可以使用 & 符号来计算两个或更多集合的交集,即返回集合 a 和集合 b 中都包含的元素。其语法格式如下:

set_a & set_b  # 相当于set_a.intersection(set_b)
参数说明: 
1.set_a: 集合 a。
2.set_b: 集合 b,参数可以是一个或多个集合。
3.返回值: 返回集合的交集。

集合 intersection() 方法用于返回集合的交集,即返回 集合a集合b 中都包含的元素。但是不改变 原集合a原集合b。其语法格式如下:

set_a.intersection(set_b)  # 相当于set_a & set_b
参数说明:
1.set_a:集合a
2.set_b:集合b,可以是集合或其他的可迭代对象(如列表、元组、字典等),可以是一个或多个可迭代对象,多个可迭代对象之间
用逗号隔开
3.返回值:将多个集合取交集,并将交集作为一个新的集合返回

集合中的 intersection_update() 方法用于更新原集合为两个集合的交集,即把 集合a 更新为 集合a集合b 的交集,但不改变 集合b。其语法格式如下:

set_a.intersection_update(set_b)
参数说明:
1.set_a: 集合a
2.set_b: 集合b,参数可以是集合或其他的可迭代对象(如列表、元组、字典等),可以是一个或多个可迭代对象,多个可迭代对象之间
用逗号隔开。
3.返回值:None

示例代码:

# 计算两个集合的交集
# 创建集合
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
# 返回集合的交集
print('a、b的交集: ', a & b)  # 返回{3, 4}
# 计算多个集合的交集
# 创建集合
surname1 = {'赵', '钱', '孙', '李'}
surname2 = {'周', '赵', '王', '孙'}
surname3 = {'赵', '孙', '褚', '陈'}
print('多个集合的交集为: ', surname1 & surname2 & surname3)
# 在集合中'&'不等于'and'
list1 = [1, 3, 5, 7, 9, 9, 1]  # 列表数据1
list2 = [2, 4, 6, 7, 8, 7, 4]  # 列表数据2
set1 = set(list1)  # 将列表1转换为集合1
set2 = set(list2)  # 将列表2转换为集合2
print('and结果为: ', set1 and set2)
print('&结果为: ', set1 & set2)
print('------------------------------------------------------')
n1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}  # 创建集合
n2 = (2, 11, 20, 9)  # 创建元组
n3 = [50, 100, 1, 8, 9]  # 创建列表
n4 = []  # 创建空列表
# 返回集合的交集
print('n1、n2的交集: ', n1.intersection(n2))
print(n1)
print('n1、n3的交集: ', n1.intersection(n3))
print('n1、n2、n3的交集: ', n1.intersection(n2, n3))
print('n1、n2、n3、n4的交集: ', n1.intersection(n2, n3, n4))  # 返回空集合
print('------------------------------------------------------')
n1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}  # 创建集合n1
n2 = {1, 2, 9, 11, 20}  # 创建集合n2
n3 = [1, 8, 9, 20, 50, 100]  # 创建列表n3
print('更新前的集合n1: ', n1)
n1.intersection_update(n2, n3)  # 更新n1为n1、n2、n3的交集
print('更新后的集合n1: ', n1)
print('更新前的集合n2: ', n2)
n2.intersection_update(n3)  # 更新n2为n2与n3的交集
print('更新后的集合n2: ', n2)
print('------------------------------------------------------')
# intersection()方法和intersection_update()方法的区别
print('*********** intersection()方法 ***********')
a = {1, 2, 3, 4, 5}  # 创建集合a
b = {5, 6, 7, 8}  # 创建集合b
print('取交集前的集合a: ', a)
print('取交集前的集合b: ', b)
a.intersection(b)  # 返回集合的交集
print('返回: ', a.intersection(b))  # 生成集合的交集并返回
print('取交集后的集合a: ', a)  # 不改变集合a
print('取交集后的集合b: ', b)  # 不改变集合b
print('\n******** intersection_update()方法 ********')
a = {1, 2, 3, 4, 5}  # 创建集合a
b = {5, 6, 7, 8}  # 创建集合b
print('更新前的集合a: ', a)
print('更新前的集合b: ', b)
a.intersection_update(b)  # 更新原集合为两个集合的交集
print('返回: ', a.intersection_update(b))  # 返回None
print('更新后的集合a: ', a)  # 更新集合a
print('更新后的集合b: ', b)  # 不改变集合b
2.4.2.2 “^”、symmetric_difference()方法、symmetric_difference_update()方法-------对称差集

可以使用 ^ 符号来计算两个集合的对称差集。即返回由集合 a 和集合 b 中不重复的元素组成的集合。其语法格式如下:

set_a ^ set_b  # 相当于set_a.symmetric_difference(set_b)
参数说明:
1.set_a: 集合 a。
2.set_b: 集合 b。
3.返回值: 返回对称差集。

示例代码:

# 创建集合
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
c = {1, 3, 10}
# 返回集合的对称差集
print("a、b的对称差集:", a ^ b)  # 返回{1, 2, 5, 6}
print("a、c的对称差集:", a ^ c)  # 返回{2, 4, 10}
print("b、c的对称差集:", b.symmetric_difference(c))  # 返回{1, 4, 5, 6, 10}
print(a, b, c)  # {1, 2, 3, 4} {3, 4, 5, 6} {1, 10, 3}
a.symmetric_difference_update(c)  # 会就地修改a
print(a, b, c)  # {2, 4, 10} {3, 4, 5, 6} {1, 10, 3}
2.4.2.3 “|”、union()方法、update()方法-------并集

可以使用 | 符号来计算两个或更多集合的并集,即将集合 a 和集合 b 中的元素合并在一起。其语法格式如下:

set_a | set_b  # 相当于set_a.union(set_b)
参数说明:
1.set_a: 集合 a。
2.set_b: 集合 b,参数可以是一个或多个集合。
3.返回值: 返回集合的并集。
提示:执行集合的并集操作时,重复的元素会自动保留一个。集合的并集操作,也可以使用 union() 方法。
update() 方法之 2.3.2 update()方法–更新原集合为两个集合的并集 一小节中已经讲过,这里不再赘述

示例代码:

# 创建集合
a = {1, 2}
b = {3, 4, 5, 6}
c = {1, 3, 10}
# 返回集合的并集
print("a、b的并集:", a | b)  # 返回{1, 2, 3, 4, 5, 6}
print("a、b、c的并集:", a | b | c)  # 返回{1, 2, 3, 4, 5, 6, 10}
print("a、c的并集:", a.union(c))  # 返回{1, 2, 3, 10}
# 在集合中"|"不等于"or"
a = 'python'  # 字符串数据a
b = 'pycharm'  # 字符串数据b
set1 = set(a)  # 将字符串a转换为集合1
set2 = set(b)  # 将字符串b转换为集合2
print('or结果为:', set1 or set2)
print('|结果为:', set1 | set2)
2.4.2.4 “-”、difference()方法、difference_update()方法 -------差集

可以使用 - 符号来计算两个或更多集合的差集。即集合元素包含在集合 a 中,但不包含在集合 b 中。其语法格式如下:

set_a - set_b  # 相当于set_a.difference(set_b)
参数说明: 
1.set_a: 集合 a。
2.set_b: 集合 b,参数可以是一个或多个集合。
3.返回值: 返回集合的差集。
ps: difference_update()方法--将原集合更新为两个集合的差集 

示例代码:

# 创建集合
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
c = {1, 3, 10}
# 返回集合的差集
print("a与b的差集:", a - b)  # 返回{1, 2}
print("a与c的差集:", a - c)  # 返回{2, 4}
print("a与b、c的差集:", a - b - c)  # 返回{2}
print("b与c的差集:", b.difference(c))  # 返回{4, 5, 6}
print("c与b的差集:", c.difference(b))  # 返回{1, 10}
print("*********** difference()方法 ***********")
a = {"赵", "钱", "孙", "李", "周"}  # 创建集合a
b = {"孙", "李"}  # 创建集合b
print("取差集前的集合a:", a)
print("取差集前的集合b:", b)
a.difference(b)  # 返回集合的差集
print("返回:", a.difference(b))  # 生成集合的差集并返回
print("取差集后的集合a:", a)  # 不改变集合a
print("取差集后的集合b:", b)  # 不改变集合b
print("\n******** difference_update()方法 ********")
a = {"赵", "钱", "孙", "李", "周"}  # 创建集合a
b = {"孙", "李"}  # 创建集合b
print("更新前的集合a:", a)
print("更新前的集合b:", b)
a.difference_update(b)  # 更新原集合为两个集合的差集
print("返回:", a.difference_update(b))  # 返回None
print("更新后的集合a:", a)  # 更新集合a
print("更新后的集合b:", b)  # 不改变集合b
2.4.2.5 “<=”、issubset()方法、 -------判断当前集合是否为另一个集合的子集

可以使用 <= 运算符判断当前集合是否为另一个集合的子集,即判断集合 a 中的所有元素是否都包含在集合 b 中。其语法格式如下:

set_a <= set_b  # 相当于set_a.issubset(set_b)
参数说明: 
1.set_a: 集合 a。
2.set_b: 集合 b。
3.返回值: 返回布尔值,如果集合 a 中的所有元素都包含在集合 b 中,则返回 True,否则返回 False

【示例1】 判断一个集合是否为另一个集合的子集。

# 创建集合
a = {1, 2, 3, 4}
b = {1, 3, 4, 5, 6}
c = {1, 3}
d = {3, 1}
# 判断集合是否为另一个集合的子集
print("a<=b返回:", a <= b)  # 返回False
print("c<=a返回:", c <= a)  # 返回True
print("c<=d返回:", c <= d)  # 返回True
print("c.issubset(b)返回:", c.issubset(b))  # 返回True

【示例2】 使用“<”运算符判断当前集合是否为另一个集合的真子集。子集就是一个集合中的全部元素是另一个集合中的元素,有可能与另一个集合相等;真子集就是一个集合中的元素全部是另一个集合中的元素,但不存在相等。

# 创建集合
a = {"Python", "Java"}
b = {"Java", "Python"}
c = {"Java", "PHP", "C#"}
# 判断一个集合是否为另一个集合的子集
print("a<=b返回:", a <= b)  # 返回True
print("a<=c返回:", a <= c)  # 返回False
# 判断一个集合是否为另一个集合的真子集
print("a<b返回:", a < b)  # 返回False
print("a<c返回:", a < c)  # 返回False
2.4.2.6 “==”、isdisjoint()方法 -------判断两个集合是否相等

可以使用 == 运算符判断两个集合是否相等(包含相同的元素),即判断集合 a 和集合 b 中的元素是否相同。其语法格式如下:

set_a == set_b
参数说明:
1.set_a: 集合 a。
2.set_b: 集合 b。
3.返回值: 返回布尔值,如果集合 a 和集合 b 中的元素相同,则返回 True,否则返回 False。
ps: !===刚好相反,如果集合a和集合b中的元素相同,则返回False,否则返回True。set_a != set_b

isdisjoint()方法--判断两个集合是否包含相同的元素
set_a.isdisjoint(set_b)
参数说明: 
1.set_a: 集合a。
2.set_b: 集合b,可以是一个集合或其他的可迭代对象(如列表、元组、字典等)。
3.返回值: 返回布尔值,如果两个集合没有相同元素则返回True,否则返回 False

示例代码:

# 创建集合
a = {"刀", "枪", "剑", "戟"}
b = {"戟", "剑", "枪", "刀"}
c = {"斧", "钺", "钩", "叉"}
# 判断两个集合是否相等
print("a==b返回:", a == b)  # 返回True
print("a==c返回:", a == c)  # 返回False
print("a!=b返回:", a != b)  # 返回False
print("a!=c返回:", a != c)  # 返回True
print('----------------------------------------')
x = {"one", "two", "three", "four"}  # 创建集合x
y = {"three", "four", "five"}  # 创建集合y
z = ("zero", 1, 2, 3)  # 创建元组z
print(x.isdisjoint(y))  # x和y中有相同的元素,返回False
print(x.isdisjoint(z))  # x和z中没有相同的元素,返回True
print(y.isdisjoint(z))  # y和z中没有相同的元素,返回True
2.4.2.7 “>=”、issuperset()方法 -------判断当前集合是否为另一个集合的超集

可以使用 >= 运算符判断当前集合是否为另一个集合的超集,即判断集合 b 中的所有元素是否都包含在集合 a 中。其语法格式如下:

set_a >= set_b  # 相当于set_a.issuperset(set_b)
参数说明: 
1.set_a: 集合 a。
2.set_b: 集合 b。
3.返回值:返回布尔值,如果集合 b 中的所有元素都包含在集合 a 中,则返回 True,否则返回 False

示例代码:

# 创建集合
a = {'赵', '钱', '孙', '李'}
b = {'赵', '孙', '李', '周', '吴'}
c = {'赵', '孙'}
d = {'王', '郑'}
# 判断集合是否为另一个集合的超集
print("a>=b返回:", a >= b)  # 返回False
print("b>=c返回:", b >= c)  # 返回True
print("a>=c返回:", a >= c)  # 返回True
print("a.issuperset(d)返回:", a.issuperset(d))  # 返回False
# 创建集合
a = {"001", "003", "005"}
b = {"003", "005"}
c = {"005", "003"}
# 判断一个集合是否为另一个集合的超集
print("a>=b返回:", a >= b)  # 返回True
print("b>=c返回:", b >= c)  # 返回True
# 判断一个集合是否为另一个集合的真超集
print("a>b返回:", a > b)  # 返回True
print("b>c返回:", b > c)  # 返回False

2.5 检测元素

使用 in 关键字可以检测一个集合中是否存在指定的元素,如果存在,则返回 True;否则返回 False。使用 not in 关键字也可以检测一个值,返回值与 in 关键字相反。示例代码1:

set1 = {'a', 'b', 'c', 'd'}
if 'a' in set1:
    set1.remove('a')
if 'd' in set1:
    set1.remove('d')
print(set1)

示例代码2:

print(10 in [1, 2, 3])
print(10 in {1, 2, 3})
# 如果列表和集合的元素都有100万个,谁的效率高?
# 1.线性数据结构,搜索元素的时间复杂度是O(n),即随着数据规模增加耗时增大
# 2.set、dict使用hash表实现,内部使用hash值作为key,时间复杂度为O(1),查询时间和数据规模无
# 关,不会随着数据规模增大而搜索性能下降。

在 Ipython 中进行测试,如下:

In [26]: %%timeit lst1 = list(range(100))
    ...: a = -1 in lst1
    ...:
    ...:
682 ns ± 14.6 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

In [27]: %%timeit lst1 = list(range(1000000))
    ...: a = -1 in lst1
    ...:
    ...:
7.24 ms ± 67.7 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [28]: %%timeit set1 = set(range(100))
    ...: a = -1 in set1
    ...:
    ...:
19.7 ns ± 0.137 ns per loop (mean ± std. dev. of 7 runs, 100,000,000 loops each)

In [29]: %%timeit set2 = set(range(1000000))
    ...: a = -1 in set2
    ...:
    ...:
19.9 ns ± 0.168 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)

2.6 copy()方法–复制一个集合

集合中的 copy() 方法用于复制一个集合。其语法格式如下:

set.copy()
参数说明: 
set: 表示需要复制的集合。
返回值: 返回复制后的新集合。

示例:

old_num = set(["0002", "0001", "0003"])  # 将列表转换为集合
new_num = old_num.copy()  # 复制集合
print(new_num)
# 直接赋值和copy()方法的区别
a = {1, 2, 3, 4, 5}  # 创建集合a
b = a  # 直接赋值
c = a.copy()  # 复制一个集合
print("a:", a)
print("b:", b)
print("c:", c, "\n")
a.add("Python")  # 添加指定元素到集合a
print("a:", a)
print("b:", b)
print("c:", c, "\n")
b.discard(5)  # 移除b中的指定元素
print("a:", a)
print("b:", b)
print("c:", c, "\n")
c.clear()  # 清空集合c
print("a:", a)
print("b:", b)
print("c:", c)
  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Amo Xiang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值