python学习 day5
set类型(集合)
无序且不重复的元素集合(可以简单快速的记忆:就是一个无序,不允许重复的列表)
创建:
s = {11, 22, 33}
注意:比如传入的是列表或者元组等,他会去遍历对象;然后将遍历出来的元素增加到自己内部中去;如果有重复的则将不再创建新的列表元素。
li = [11, 22, 11, 33,22] s = set(li) print(s) # 结果{33, 11, 22}
方法详情
class set(object): """ set() -> new empty set object set(iterable) -> new set object Build an unordered collection of unique elements. """ def add(self, *args, **kwargs): # real signature unknown """ Add an element to a set,添加元素 This has no effect if the element is already present. """ pass def clear(self, *args, **kwargs): # real signature unknown """ Remove all elements from this set. 清除内容""" pass def copy(self, *args, **kwargs): # real signature unknown """ Return a shallow copy of a set. 浅拷贝 """ pass def difference(self, *args, **kwargs): # real signature unknown """ Return the difference of two or more sets as a new set. A中存在,B中不存在 (i.e. all elements that are in this set but not the others.) """ pass def difference_update(self, *args, **kwargs): # real signature unknown """ Remove all elements of another set from this set. 从当前集合中删除和B中相同的元素""" pass def discard(self, *args, **kwargs): # real signature unknown """ Remove an element from a set if it is a member. If the element is not a member, do nothing. 移除指定元素,不存在不报错 """ pass def intersection(self, *args, **kwargs): # real signature unknown """ Return the intersection of two sets as a new set. 交集 (i.e. all elements that are in both sets.) """ pass def intersection_update(self, *args, **kwargs): # real signature unknown """ Update a set with the intersection of itself and another. 取交集并更更新到A中 """ pass def isdisjoint(self, *args, **kwargs): # real signature unknown """ Return True if two sets have a null intersection. 如果没有交集,返回True,否则返回False""" pass def issubset(self, *args, **kwargs): # real signature unknown """ Report whether another set contains this set. 是否是子序列""" pass def issuperset(self, *args, **kwargs): # real signature unknown """ Report whether this set contains another set. 是否是父序列""" pass def pop(self, *args, **kwargs): # real signature unknown """ Remove and return an arbitrary set element. Raises KeyError if the set is empty. 移除元素 """ pass def remove(self, *args, **kwargs): # real signature unknown """ Remove an element from a set; it must be a member. If the element is not a member, raise a KeyError. 移除指定元素,不存在保错 """ pass def symmetric_difference(self, *args, **kwargs): # real signature unknown """ Return the symmetric difference of two sets as a new set. 对称差集 (i.e. all elements that are in exactly one of the sets.) """ pass def symmetric_difference_update(self, *args, **kwargs): # real signature unknown """ Update a set with the symmetric difference of itself and another. 对称差集,并更新到a中 """ pass def union(self, *args, **kwargs): # real signature unknown """ Return the union of sets as a new set. 并集 (i.e. all elements that are in either set.) """ pass def update(self, *args, **kwargs): # real signature unknown """ Update a set with the union of itself and others. 更新 """ pass
.add(*args, **kwargs):添加元素==>直接在原有的基础上增加
se = set() se.add(44) se.add(33) # 一次只能增加一个,多了会报错 print(se) # 结果{33, 44}
问题:我们知道set集合的创建有2中方式;如果我们用大括号这种?
se = {11, 22, 33}
se.add(55) # 一次只能增加一个,多了会报错
print(se) #结果 {33, 11, 22, 55}
# 但是此时如果{}里面的内容为空的话会怎样?
se = {}
se.add(55)
print(se) #结果 报错!
分析上面报错的原因:
se = {} # 当我们创建后我们我们可以看看se的类型: print(type(se)) # 结果<class 'dict'>
分析结果:se = {} 这样创建的不是set类型;而是字典(dict)类型,而字典没有add方法;所以报错!
.clear():清除
se = {11, 22, 33}
print(se.clear()) # 结果 None
# set()创建的
se = set()
se.add(55)
se.add(22)
print(se.clear()) # 结果 None
s1 = {11, 22, 33}
s2 = {11, 55, 66}
print(s1.difference(s2)) # 结果 {33, 22}
# 将s1与s2互换
print(s2.difference(s1)) # 结果 {66, 55}
.difference_update():找出方法前面对象里存在有的元素;而方法后面对象不存在的元素,然后删除前后对象共有的元素;然后更新增加==》元素本身(s1或s2)会改变;内容会被更新;此方法不会返回值
注意:方法后面的元素不受影响
s1 = {11, 22, 33}
s2 = {11, 55, 66}
print(s1.difference_update(s2)) # None
print(s1) # 结果 {33, 22}
# 将s1与s2互换
s1 = {11, 22, 33}
s2 = {11, 55, 66}
print(s2.difference_update(s1)) # None
print(s2) # 结果 {66, 55}
注意:两个difference的区别。
.discard():移除指定元素,不存在不报错
se = {11, 22, 33}
se.discard(11)
print(se) # 结果:{33, 22}
se.discard(44)
print(se) # 结果:{33, 22}
.remove():移除指定元素;不存在会报错
se = {11, 22, 33}
se.remove(11)
print(se) # 结果:{33, 22}
se.remove(44)
print(se) # 结果:报错
.intersection():取得交集==》返回一个集合
s1 = {11, 22, 33}
s2 = {"ah", 11, 5}
j = s1.intersection(s2)
print(j) # 结果{11}
print(s1) # {33, 11, 22} -->对象本身不变化
.intersection_update:去除交集,并更新元素本身;不共有的被删除;只剩共有值==》此方法不会产生新值
注意:方法后面的元素在操作中不受影响
s1 = {11, 22, 33}
s2 = {"ah", 11, 5}
j = s1.intersection_update(s2)
print(j) # None
print(s1) # {11} -->对象本身变化;只剩下交集
print(s2) # 元素后面的对象没变化 {'ah', 11, 5}
.isdisjoint():判断没有交集==》返回(没有是)True/(有是)False
s1 = {11, 22, 33}
s2 = {"ah", 11, 5}
j = s1.isdisjoint(s2)
print(j) # 结果 False
.issubset():判断是不是子序列==》返回True/False
注意:判断的是方法前面的是不是方法后面的子序列:一定要弄清顺序
s1 = {11, 22, 33}
s2 = {"ah", 11, 5}
s3 = {11, 22}
j = s1.issubset(s2) # 判断s1是不是s2的子序列
k = s3.issubset(s1) # 判断s3是不是s1的子序列
m = s1.idsubset(s3) # 判断s1是不是s3的子序列
print(j) # 结果 False
print(k) # 结果 True
print(m) # 结果 False
s1 = {11, 22, 33}
s2 = {"ah", 11, 5}
s3 = {11, 22}
j = s1.issuperset(s2) # 判断s1是不是s2的父序列
k = s3.issuperset(s1) # 判断s3是不是s1的父序列
m = s1.issuperset(s3) # 判断s1是不是s3的父序列
print(j) # 结果 False
print(k) # 结果 False
print(m) # 结果 True
总结:issubset()和issuperset():他们之间比较的子, 父关系;是看对应的对象里的每个元素;是否被包含,或包含的关系;
.pop():移除元素==》移除的过程会返回这个移除的值;可以用变量接收
s1 = {11, 22, 33, 44}
p = s1.pop() # 会返回一个值;然后用变量可以接收
print(p) # 结果 33
print(s1) # 结果 {11, 44, 22}
.symmetric_difference():对称差集,然后返回差集组合的新对象
s1 = {11, 22, 33, 44}
s2 = {55, 11, 22, 66}
r1 = s1.difference(s2) # 获得s1有而s2没有的值
r2 = s2.difference(s1) # 获得s2有而s1没有的值
print(r1) # 结果{33, 44}
print(r2) # 结果{66, 55}
# 使用 s1.symmetric_difference()
ret = s1.symmetric_difference(s2)
print(ret) # 结果{33, 66, 44, 55}
总结:相当于;将2个集合中不同的元素拿出来组成一个新的集合
s1 = {11, 22, 33, 44}
s2 = {55, 11, 22, 66}
ret = s1.symmetric_difference_update(s2)
print(ret) # 结果None
print(s1) # 结果{33, 66, 44, 55}-->方法前面的(s1)集合内容被替换掉
print(s2) # 结果 {66, 11, 22, 55}--》方法后面的集合(s2)不受影响
.union():取并集,取方法前后集合的所有值;组成新的集合,并让重复值,值显示一次==》返回新的集合
s1 = {11, 22, 33, 44}
s2 = {55, 11, 22, 66}
ret = s1.union(s2)
print(ret) # 结果 {33, 66, 11, 44, 22, 55}
# 当两个集合值不同时;可以组和两个集合
s1 = {11, 22, 33, 44}
s2 = {55, 66}
ret = s1.union(s2)
print(ret) # 结果 {33, 66, 22, 55, 11, 44}
.update:更新==》直接更新方法前面的原始集合,不产生新的对象
注意:更新的是方法前面的集合,后面的不受影响
s1 = {11, 22, 33, 44}
s2 = {55, 66}
s1.update(s2)
print(s1) # 结果{33, 66, 22, 55, 11, 44}
print(s2) # 结果{66, 55} 方法后面的不受影响
# 可以传入列表 等
s1 = {11, 22, 33, 44}
s1.update(["haha",489])
print(s1) #结果{33, 489, 11, 44, 'haha', 22}
练习:数据更新
old_dict = { "#1":11, "#2":22, "#3":100, } new_dict = { "#1":33, "#4":22, "#7":100, } # 获取旧数据中的key,并转换成set集合 old_set = set(old_dict.keys()) # 获取新数据中的key,并转换成set集合 new_set = set(new_dict.keys()) # 取出两个集合中的共有元素 in_set = old_set.intersection(new_set) # 遍历取出的共有元素 for i in in_set: # 新/旧共有的数据;用新数据中key值对应的value值替换旧的数据 old_dict[i] = new_dict[i] # 获取旧数据中有的;而新数据中没有的数据; j2 = old_set.difference(new_set) # 遍历获取旧数据中的独有数据 for k in j2: # 将旧数据中的独有数据删除 old_dict.pop(k) # 获取新数据中有的;而旧数据中没有的数据 j3 = new_set.difference(old_set) # 循环获取的新数据独有的数据 for c in j3: # 将其数据赋给旧数据;达到新数据替换旧数据的作用 old_dict[c] = new_dict[c] # 将整理完的数据打印 print(old_dict)
三目运算(三元运算)
理解性记忆:(我们之前学的)
if 条件: name = "haha" else: name = "heihei"
用三元运算表示:
name = "值1" if 条件 else "值2"
# 条件成立 name = "haha" if 1 == 1 else "heihei" print(name) # 结果 haha # 条件不成立 name = "haha" if 1 == 2 else "heihei" print(name) # 结果 heihei
浅拷贝和深拷贝
一 数字和字符串
对于 数字 和 字符串 而言,赋值、浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址。
import copy # 引入的copy模块 # ######### 数字、字符串 ######### n1 = 123 # n1 = "i am alex age 10" print(id(n1)) # ## 赋值 ## n2 = n1 print(id(n2)) # ## 浅拷贝 ## n2 = copy.copy(n1) print(id(n2)) # ## 深拷贝 ## n3 = copy.deepcopy(n1) print(id(n3))

二 其他基本数据类型
对于字典、元祖、列表 而言,进行赋值、浅拷贝和深拷贝时,其内存地址的变化是不同的。
n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 678]}
n2 = n1

2. 浅拷贝
浅拷贝,在内存中只额外创建第一层数据
import copy # 引入copy模块 n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 678]} n3 = copy.copy(n1)

import copy n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 678]} n4 = copy.deepcopy(n1)

函数
一 背景
在学习函数之前,一直遵循:面向过程编程,即:根据业务逻辑从上到下实现功能,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,也就是将之前实现的代码块复制到现需功能处,如下:
while True: if cpu利用率 > 90%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 硬盘使用空间 > 90%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 内存占用 > 80%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接
腚眼一看上述代码,if条件语句下的内容可以被提取出来公用,如下:
def 发送邮件(内容) #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 while True: if cpu利用率 > 90%: 发送邮件('CPU报警') if 硬盘使用空间 > 90%: 发送邮件('硬盘报警') if 内存占用 > 80%:
对于上述的两种实现方式,第二次必然比第一次的重用性和可读性要好,其实这就是函数式编程和面向过程编程的区别:
- 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
- 面向对象:对函数进行分类和封装,让开发“更快更好更强...”
二 定义和使用
def 函数名(参数): ... 函数体 ... 返回值 # 没有返回值;结果为None
函数的定义主要有如下要点:
- def:表示函数的关键字
- 函数名:函数的名称,日后根据函数名调用函数
- 函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...
- 参数:为函数体提供数据
- 返回值:当函数执行完毕后,可以给调用者返回数据。如果没设返回值;结果则为None
1、返回值
def 发送短信(): 发送短信的代码... if 发送成功: return True else: return False while True: # 每次执行发送短信函数,都会将返回值自动赋值给result # 之后,可以根据result来写日志,或重发等操作 result = 发送短信() if result == False: 记录日志,短信发送失败..
2、参数
问题:为什么需要参数那?
无参数实现:
def CPU报警邮件() #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 def 硬盘报警邮件() #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 def 内存报警邮件() #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 while True: if cpu利用率 > 90%: CPU报警邮件() if 硬盘使用空间 > 90%: 硬盘报警邮件() if 内存占用 > 80%: 内存报警邮件() 无参数实现
有参数实现:
def 发送邮件(邮件内容) # 邮件内容称法上叫 形式参数-->简称 形参 #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 while True: if cpu利用率 > 90%: 发送邮件("CPU报警了。") # 调用的时候传入的参数叫 实际参数-->简称 实参 if 硬盘使用空间 > 90%: 发送邮件("硬盘报警了。") if 内存占用 > 80%: 发送邮件("内存报警了。") 有参数实现
函数的有三中不同的参数:
- 普通参数
- 默认参数
- 动态参数
普通参数:
# ######### 定义函数 ######### # name 叫做函数func的形式参数,简称:形参 def func(name): print name # ######### 执行函数 ######### # 'wupeiqi' 叫做函数func的实际参数,简称:实参 func('wupeiqi')
默认参数:-->放在参数的最后
def func(name, age = 18): print "%s:%s" %(name,age) # 指定参数 func('wupeiqi', 19) # 结果 wupiqi:19 # 使用默认参数 func('alex') # 结果 alex:18 注:默认参数需要放在参数列表最后
动态参数:
1、在形参前面加一个 * :传入的参数会形成一个元组(tuple)
def func(*args): print args # 执行方式一 func(11,33,4,4454,5) # 返回的结果会形成个元组(11,33,4,4454,5) # 执行方式二 li = [11,2,2,3,3,4,54] func(*li) # 加了 * 相当于循环了整个列表,将其中的每个元素单独拿出来当实参传入 # 如果直接输入 li = [11, 22, 33] func(li) # 结果([11, 2, 33],) 会将整个列表当成元素的一个元素
2、在形参前面加2个 **:传入的参数形成一个字典(list)
def func(**kwargs): print args # 执行方式一 func(name='haha',age=18) # 传入参数的形式必须是一个key;对应一个value 结果 {'age': 18, 'name': 'haha'} # 执行方式二 li = {'name':'haha', age:18, 'gender':'male'} func(**li)
3、万能参数:传入的形参由加一个 * 和2个 * 的组合:会根据传入的参数形式;自动对应形成列表或元组
def aa(*b, **c): # 注意:一个*和2**的位置(都在最后面):一个*必须在 ** 的前面;不能放在 **的后面去;不然报错; # 这个是规定 print(b, type(b)) # 结果 (11, 22, 33) <class 'tuple'> print(c, type(c)) # 结果 {'k2': 'haha', 'k1': 123} <class 'dict'> aa(11, 22, 33, k1=123,k2="haha")
在这种情况下;我们同样可以传入普通参数:-->会依次将实参的值赋予对应的形参值上
def aa(a, *b, **c): print(a, type(a)) # 结果 11 <class 'int'> print(b, type(b)) # 结果 (22, 33) <class 'tuple'> print(c, type(c)) # 结果 {'k2': 'haha', 'k1': 123} <class 'dict'> aa(11, 22, 33, k1=123,k2="haha")

4、指定参数:
实参的传入不一定要按形参的顺序;但是,必须要将形参中的变量名加上才行(具体操作看下面的视图)-->指定形参的值

如果我们改变传入参数的顺序:(而且要让程序正常执行的操作)

扩展:发送邮件实例
import smtplib from email.mime.text import MIMEText from email.utils import formataddr msg = MIMEText('邮件内容', 'plain', 'utf-8') msg['From'] = formataddr(["武沛齐",'wptawy@126.com']) msg['To'] = formataddr(["走人",'424662508@qq.com']) msg['Subject'] = "主题" server = smtplib.SMTP("smtp.126.com", 25) server.login("wptawy@126.com", "邮箱密码") server.sendmail('wptawy@126.com', ['424662508@qq.com',], msg.as_string()) server.quit() 发送邮件实例

- 在形参前面加一个 *;传入的参数会形成一个元组(tuple)
- 在形参前面加2个 **;传入的参数会形成一个字典(list)
- 注意:一个 * 和2个 *的位置(都必须在最后面):一个 * 必须在 ** 的前面;不能放在 **的后面去;不然报错;这个是规定
- 一个 * 的args 和两个 * 的kwargs:这个是大家公用的写法。大家都这么写
全局变量和局部变量
局部变量:函数内部定义的;只能在函数内使用的,在函数体外不能用。
def aa(): a = 123 # 在函数体里面定义的就是局部变量;离开函数体就没用了 这个 a 就是 局部变量 print(a) print(a) # 出现报错!因为 a 没定义;页面上的 a 是局部的;外面不能享受的
全局变量:在函数体外定义的;在程序任何位置都可以用
a = 123 # 在函数外面定义的就是全局变量;任何位置都可以用 这个 a 就是 全局变量 def aa(): print(a) aa() # 结果 123 print(a) # 结果 123
注意:全局变量在局部虽然能被调用;但是在局部却没办法修改
a = 123 # 在函数外面定义的就是全局变量;任何位置都可以用 def aa(): a = 456 # 这里定义的 a 是不能改变全局的 a 的;他和全局的 a 是2个意思 # 两个是完全不同的变量 print(a) def bb(): print(a) # 结果会输出 123 说明 aa()中没有改变全局变量 a 的值 aa() # 结果 456 bb() # 结果 123
那如果我非要改变那?==》加入 global 关键字
a = 123 # 在函数外面定义的就是全局变量;任何位置都可以用 def aa(): global a # 这个 global 关键字的意思;是说明这个 a 是来自全局变量的 a = 456 print(a) def bb(): print(a) # 结果会输出 456 说明 aa()中改变全局变量 a 的值 aa() # 结果 456 bb() # 结果 456
浙公网安备 33010602011771号