5-python的封装与结构 - set集合
1 封装与解构
封装与解构属于Python语言的一种特性,它使用起来很像其他语言中的"逗号表达式"
,但内部原理是不同的,在某些场景下:比如变量交换复制时使用,显得非常优雅。
1.1 封装
封装故名思议就是装箱,把多个值使用逗号分隔,组合在一起,本质上来看,其返回的是一个元组,只是省略了小括号。(一定要区别与C语言的逗号表达式)
In [91]: t1 = (1,2) # 定义一个元组
In [92]: t2 = 1,2 # 省略括号,其内部还是会封装成元组
In [93]: t1
Out[93]: (1, 2)
In [94]: t2
Out[94]: (1, 2)
In [95]: type(t1)
Out[95]: tuple
In [96]: type(t2)
Out[96]: tuple
1.2 解构
解构,解构,就是把箱子解开,在Python中表示从线性结构中把元素解开,并且顺序的赋值给其他变量,需要注意的是,解构时接受元素的变量,需要放在等式的左边,并且数量要和右边解开的元素的个数一致。
In [97]: t1
Out[97]: (1, 2)
In [98]: a,b = t1 # 表示把1赋给a,把2赋给b
In [99]: a
Out[99]: 1
In [100]: b
Out[100]: 2
In [101]: a,b,c = t1 # 当接受元素的变量多余解构的元素时,会提示ValueError,反之相同
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-101-2e8ad53e5fc7> in <module>
----> 1 a,b,c = t1
ValueError: not enough values to unpack (expected 3, got 2)
In [102]:
1.3 Python3的解构
了解了封装与解构,那么回想一下当我们需要进行变量交换的时候,是否可以通过封装与解构进行优化呢?当我们在其他语言中进行a,b变量的值的交换,我们需要一个中间变量temp,即:a = temp,a = b,b = temp
,在Python中我们可以省略。
>>> a = 1
>>> b = 200
>>> a,b = b,a # 这样就完成了变量的交换了,是不是很方便
>>> a
200
>>> b
1
>>>
为什么可以使用这种骚操作,是因为Python在进行变量赋值时,会先计算等式右边的表达式,封装起来,然后再进行解构,赋给对应位置上的变量。并且还提供了其他更便捷的方法比如*号。
*号
: 使用方式为:*变量名
,贪婪的吸收解构的元素形成一个列表,无论能否吸收,都会返回一个列表。_号
:表示丢弃一个变量(实际上是使用_
接受变量,但是使用这么一个符号,就表示我们不想用它)
In [1]: t = list(range(5))
In [2]: t
Out[2]: [0, 1, 2, 3, 4]
In [3]: head,*mid,tail = t
In [4]: head
Out[4]: 0
In [5]: mid
Out[5]: [1, 2, 3]
In [6]: tail
Out[6]: 4
需要注意的是:
- *变量名,这种格式不能单独使用
- 也不能多个*变量名,连续使用(因为从原理上看,两个、*变量名连起来使用,会引起歧义,所以Python禁止了这种写法)
- *_这种格式,可以收集足够多的元素丢弃
# 1 从[1,(2,3,4),5]中取出4来
>>> _,(*_,a),_ = [1,(2,3,4),5]
>>> a
>>> 4
# 环境变量JAVA_HOME=/usr/bin/java,返回环境变量名和路径
>>> env,path = 'JAVA_HOME=/usr/bin/java'.split('=')
>>> env,path
>>> ('JAVA_HOME','/usr/bin/java')
或者
In [9]: env, _, path = 'JAVA_HOME=/usr/bin/java'.partition('=')
In [10]: env,path
Out[10]: ('JAVA_HOME', '/usr/bin/java')
解构是Python提供的很好的功能,可以方便的提取复杂的数据结构的值,配置_使用时,会更加便捷。
2 set类型
集合set在Python中是一个非常重要的非线性结构
,它使用{}
表示,用三个词总结集合的特点就是:可变的
、无序的
、不重复
。它的官方解释如下:
- set是一个无序的,不同的
可hash对象
组成的集。 - 常用来进行成员测试,在一个序列中去掉重复的对象,和进行数学上的计算,比如
交集(intersection)
、并集(union)
、差集(difference)
、对称差集(symmetric difference)
等。 - 和其他容器类型相似,在一个无序的集合中支持
x in set
,len(set)
,for x in set
等操作。 - set不会记录元素的位置以及元素加入集合的顺序,所以set不支持
索引
,切片
或者其他的类序列的操作。
什么是可hash对象,可以简单的理解为可以被hash()计算的对象,在Python中,可hash对象是不可变类型的,比如tuple, str, int, 等等。
2.1 set的定义
Python提供了两种定义一个集合的方式,set()
和 set(iterable)
,他们的用法如下:
set() -> new empty set object --> 返回一个空的set对象
set(iterable) -> new set object --> 返回一个set对象,元素有iterable填充
例如:
In [44]: s1 = set()
In [45]: s2 = set(range(5)) # {0, 1, 2, 3, 4}
In [46]: s3 = set(list(range(10))) # 外面使用list进行转换,多此一举,{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
In [47]: s4 = {} # 这种方式实际上是创建了一个字典
In [48]: s4
Out[48]: {}
In [50]: type(s4)
Out[50]: dict
In [51]: s5 = {(1,3),3,'a'}
In [52]: s6={[1,2],(1,2,),1,2} # list属于不可hash对象,所以无法添加到set中去
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-52-237c72203405> in <module>
----> 1 s6={[1,2],(1,2,),1,2}
TypeError: unhashable type: 'list'
In [53]:
2.2 set的基本操作
set是可变的类型,那就意味着,我们可以对set进行增加、删除、修改等操作。
2.2.1 增加元素
set提供了两种定义一个集合的方式,add
和 update
,他们的用法如下:
s.add() --> None --> 在集合s中添加一个元素,如果元素存在,则什么都不做(去重特性)。(就地修改)
s.update(*other) --> None --> 把*others个可迭代可hash对象,和s进行并集,然后赋给s。(就地修改)
例
In [62]: s
Out[62]: {1, 2, 3}
In [63]: s.add('abc') # 把'abc'当作一个元素添加进去
In [64]: s
Out[64]: {1, 2, 3, 'abc'}
In [65]: s.add((1,2,3)) # 把(1,2,3) 当作一个元素添加进去
In [66]: s
Out[66]: {(1, 2, 3), 1, 2, 3, 'abc'}
In [67]: s.update(range(5),'abcdef',[5,6,7,8]) # 多个可迭代可hash对象取并集
In [68]: s
Out[68]: {(1, 2, 3), 0, 1, 2, 3, 4, 5, 6, 7, 8, 'a', 'abc', 'b', 'c', 'd', 'e', 'f'}
2.2.2 删除元素
set提供了多种定义一个集合的方式,比如 remove
,pop
,他们的用法如下:
s.remove() --> None --> 在集合s中删除一个元素,这个元素必须存在集合s中,否则会报KeyError异常
s.pop() --> item --> 在集合s中随便弹出一个元素,并返回元素的本身,如果集合本身为空,那么会提示KeyError异常
s.discard(elem) --> None --> 在集合s中删除一个元素,如果元素不存在集合中,那么什么也不做
s.clear() --> None --> 清空集合
例
In [71]: s
Out[71]: {(1, 2, 3), 0, 1, 2, 3, 4, 5, 6, 7, 8, 'a', 'abc', 'b', 'c', 'd', 'e', 'f'}
In [72]: s.remove(0)
In [73]: s
Out[73]: {(1, 2, 3), 1, 2, 3, 4, 5, 6, 7, 8, 'a', 'abc', 'b', 'c', 'd', 'e', 'f'}
In [74]: s.remove(1000) # 不存在集合内的元素,删除会报异常
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-74-9d9da17ab719> in <module>
----> 1 s.remove(1000)
KeyError: 1000
In [76]: s
Out[76]: {(1, 2, 3), 1, 2, 3, 4, 5, 6, 7, 8, 'a', 'abc', 'b', 'c', 'd', 'e', 'f'}
In [77]: s.pop()
Out[77]: 1
In [78]: s
Out[78]: {(1, 2, 3), 2, 3, 4, 5, 6, 7, 8, 'a', 'abc', 'b', 'c', 'd', 'e', 'f'}
In [82]: s1
Out[82]: set()
In [84]: s1.pop() # 空集合会报异常
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-84-095118de218b> in <module>
----> 1 s1.pop()
KeyError: 'pop from an empty set'
In [85]: s
Out[85]: {(1, 2, 3), 4, 5, 6, 7, 8, 'a', 'abc', 'b', 'c', 'd', 'e', 'f'}
In [86]: s.discard(1000) # 直接删除,不会返回
In [89]: s.discard(4)
In [90]: s
Out[90]: {(1, 2, 3), 5, 6, 7, 8, 'a', 'abc', 'b', 'c', 'd', 'e', 'f'}
In [92]: s.clear()
In [93]: s
Out[93]: set()
2.2.3 修改元素
上来我们需要先想一个问题,为什么要修改set呢?修改的本质是什么?
- 修改的本质其实就是找到这个元素,删除,然后在加入新的元素
- 由于集合是非线性结构,所以无法被索引
- 但是set是容器,可以被迭代
所以set不能像list那样,通过索引修改元素,因为它无序的特性,修改其实等同于删除、再添加而已。
2.2.4 成员判断
我们说既然set是容器,那么我们就可以对容器内的元素进行判断,那么就需要使用成员判断符 in
和 not in
了。
- in: x in s, 判断元素x是否是在集合s中,返回bool类型
- not in : x not in s, 判断元素x不在集合s中,返回bool类型
In [95]: s = set(range(20))
In [96]: 1 in s
Out[96]: True
In [97]: 10000 not in s
Out[97]: True
我们知道在list,str这种
线性结构
中进行成员判断
时,它的时间复杂度是O(n)
的,因为需要遍历,但是在set中就很简单了,它只需要把要判断的元素进行hash,找到set中对应的门牌号,把里面的数据拽出来,看看是不是相同。 这种操作通常都是O(1)
的,所以在set中,成员判断效率很高
,当然在dict类型
中,也是如此。
2.3 set小结
线性结构的查询时间复杂度是O(n)
,即随着数据规模的这不过大而增加耗时,set、dict等结构,内部使用的是hash值作为key,时间复杂度可以做到O(1)
查询时间和数据规模无关,在python中可hash对象有(都属于不可变类型)
- 数值类型int、float、complex
- 布尔值True、False
- 字符串String、Bytes
- 元组tuple
- None
3 集合
简单来说,所谓的一个集合,就是将数个对象归类而分成为一个或数个形态各异的大小整体。 一般来讲,集合是具有某种特性的事物的整体,或是一些确认对象的汇集。构成集合的事物或对象称作元素或是成员。集合的元素可以是任何事物,可以是人,可以是物,也可以是字母或数字等。 (此解释来自于维基百科)
- 全集:所有元素的结合。例如实数集,所有实数组成的集合就是实数集
- 子集subset和超集superset: 一个集合A所有的元素都在另一个集合B内,A是B的子集,B是A的超集
- 真子集和真超集:A是B的子集,且A不等于B,A就是B的真子集,B就是A的真超集
- 并集:多个集合合并的结果
- 交集:多个集合的公共部分
- 差集:集合中除去和其他集合共有的部分
这些是小学数学基础概念哦,兄弟们。
3.1 集合运算
通过集合运算,我们可以方便的对求出集合的差集、并集等,Python的集合除了提供了大量的集合运算方法还提供了不少的特殊符号用来表示集合运算。
3.2 并集
将集合A和集合B所有元素合并在一起,组成的集合称为集合A和集合B的并集
s.union(*other) --> new set object --> 把多个集合和集合s进行合并,返回一个新的集合对象
--> 使用 | 表示
s.update(*other) --> None --> 把*others个可迭代可hash对象,和s进行并集,然后赋给s。(就地修改)
--> 使用 != 表示
3.3 交集
集合A和集合B,由所有属于A且属于B的元素组成的集合。
s.intersection(*other) --> new set object --> 返回多个集合的交集
--> 使用 & 表示
s.intersection_update(*other) --> None --> 获取多个集合的交集,就地进行修改
--> 使用 &= 表示
3.3 差集
集合A和B,由所有属于A且不属于B的元素组成的集合。
s.difference(*others) --> new set object --> 返回集合s和其他多个集合的差集
--> 使用 - 表示
s.difference_update(*other) --> None --> 返回集合s和其他多个集合的差集,就地进行修改
--> 使用 -= 表示
3.4 对称差集
不属于集合A和集合B交集的其他元素组成的集合,数学表达式为:(A-B) U (B-A)。
s.symmetric_difference(*other) --> new set object --> 返回和另一些集合的对称差集
--> 使用 ^ 表示
s.symmetric_difference_update --> None --> 返回和另一些集合的对称差集,就地修改
--> 使用 ^= 表示
3.5 集合的其他运算
s.issubset(other) --> bool --> 判断当前集合是否是另一个集合的子集
--> 使用 <= 表示
set1 < set2 : 判断set1是否是set2的真子集
s.isssuperset(other) --> bool --> 判断当前集合是否是other的超集
--> 使用 >= 表示
set1 > set2 : 判断set1是否是other的真超集
s.isdisjoint(other) --> bool --> 判断当前集合和另一个集合有没有交集
5-python的封装与结构 - set集合的更多相关文章
- python基础之循环结构以及列表
python基础之编译器选择,循环结构,列表 本节内容 python IDE的选择 字符串的格式化输出 数据类型 循环结构 列表 简单购物车的编写 1.python IDE的选择 IDE的全称叫做集成 ...
- 第五篇:python基础之循环结构以及列表
python基础之循环结构以及列表 python基础之编译器选择,循环结构,列表 本节内容 python IDE的选择 字符串的格式化输出 数据类型 循环结构 列表 简单购物车的编写 1.pyth ...
- python爬虫主要就是五个模块:爬虫启动入口模块,URL管理器存放已经爬虫的URL和待爬虫URL列表,html下载器,html解析器,html输出器 同时可以掌握到urllib2的使用、bs4(BeautifulSoup)页面解析器、re正则表达式、urlparse、python基础知识回顾(set集合操作)等相关内容。
本次python爬虫百步百科,里面详细分析了爬虫的步骤,对每一步代码都有详细的注释说明,可通过本案例掌握python爬虫的特点: 1.爬虫调度入口(crawler_main.py) # coding: ...
- 【转】Python基础-封装与扩展、静态方法和类方法
[转]Python基础-封装与扩展.静态方法和类方法 一.封装与扩展 封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码:而外部使用者只知道一个接口(函数),只要接口(函数 ...
- python面向对象-封装-property-接口-抽象-鸭子类型-03
封装 什么是封装: # 将复杂的丑陋的隐私的细节隐藏到内部,对外提供简单的使用接口 或 # 对外隐藏内部实现细节,并提供访问的接口 为什么需要封装 1.为了保证关键数据的安全性 2.对外部隐藏内部的实 ...
- python文件封装成*.exe
python文件封装成*.exe文件(单文件和多文件) 环境:win10 64位 python3.7 原文: https://www.cnblogs.com/jackzz/p/9431923.html ...
- 将Python脚本封装成exe可执行文件 转
将Python脚本封装成exe可执行文件 http://www.cnblogs.com/renzo/archive/2012/01/01/2309260.html cx_freeze是用来将 Pyt ...
- python基础之字典dict和集合set
作者:tongqingliu 转载请注明出处:http://www.cnblogs.com/liutongqing/p/7043642.html python基础之字典dict和集合set 字典dic ...
- python继承——封装
python继承--封装 1 为什么要封装 封装数据的主要原因是:保护隐私 封装方法的主要原因是:隔离复杂度 2 封装分为两个层面 第一个层面的封装(什么都不用做):创建类和对象会分别创建二者的名称空 ...
随机推荐
- babel-preset-env: a preset that configures Babel for you
转载 babel-preset-env is a new preset that lets you specify an environment and automatically enables t ...
- Java知识点整理(一)
ArrayList和LinkedList的区别 1.ArrayList和LinkedList可想从名字分析,它们一个是Array(动态数组)的数据结构,一个是Link(链表)的数据结构,此外,它们两个 ...
- 51nod 1624 取余最短路(set)
题意: 佳佳有一个n*m的带权矩阵,她想从(1,1)出发走到(n,m)且只能往右往下移动,她能得到的娱乐值为所经过的位置的权的总和. 有一天,她被下了恶毒的诅咒,这个诅咒的作用是将她的娱乐值变为对p取 ...
- 洛谷 Roy&October之取石子
题目背景 Roy和October两人在玩一个取石子的游戏. 题目描述 游戏规则是这样的:共有n个石子,两人每次都只能取pk 个(p为质数,k为自然数,且pk小于等于当前剩余石子数),谁取走最后一个石子 ...
- Linux内核设计与实现第六周读书笔记
第三章 进程管理 3.1 进程 进程是处于执行期的代码.通常进程还要包含其他资源,像打开的文件.挂起的信号.内核的内部数据.处理器状态.一个或多个具有内存映射的内存地址空间及一个或多个执行线程,当然还 ...
- Hbase(补充)
1.用sqoop 从mysql数据库导入数据到hbase时: 可以用 sqoop list-databases --connect jdbc:mysql://192.168.1.152:3306 ...
- hadoop(三)HDFS基础使用
一.HDFS前言 1. 设计思想 分而治之:将大文件,大批量文件,分布式的存放于大量服务器上.以便于采取分而治之的方式对海量数据进行运算分析 2. 在大数据系统架构中的应用 ...
- Android之框架20160721
Android的四层架构分别为:Linux2.6内核层,核心库层,应用框架层,应用层. 其中Framework层为我们开发应用程序提供了非常多的API,我们通过调用特殊的API构造我们的APP,满足我 ...
- intellij 插件结构(文件结构以及概念层面上的结构)
1.插件内的文件 2.插件类加载器 3.插件组件(component) 4.插件的扩展以及扩展点(Extensions.Extension Points) 5.插件的Action 6.插件的Servi ...
- 使用jvisualvm工具来监控java运行情况
jvisualvm是jdk自带的工具.所以要先安装jdk 1.jvisualvm工具的路径: 通过which jvisualvm来查看 /usr/local/jdk1.7.0_79/bin/jvi ...