Python全栈之路3--set集合--三元运算--深浅拷贝--初识函数
一、上节课的重点回顾:
1、类名加括号其实就是执行类的__init__方法:
2、int
a.创建方式
n1 = 123 #根据int类创建了一个对象
n2 = int(123) #根据int类创建一个对象,类的实例化就是对象
b.int内部优化
1、n1和n2的内存地址相同
n1 = 123
n2 = n1
2、按理说n1和n2的内存地址应该不同,这是由于python的内部机制的原因,
在-5~257以内的数,按2的方式写,都是指向同一个内存
n1 = 123
n2 = 123
除此之外的数,n1和n2的内存地址是不同的,但是python源码可以改取值范围
n1 = 123123
n2 = 123123
3、id查看对象的内存地址
n1 = 123
i1 = id(n1)
name = "李露" for i in name: print(i) #循环打印每个汉字而不是字节 bytes_list = bytes(i, encoding='utf-8') #将汉字转成字节,编码是utf-8 print(bytes_list) for b in bytes_list:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
hex 可以 十进制转16进制 二进制转16进制 结果都是字符串 >>> hex(0b10) '0x2' >>> hex(10) '0xa' bin 可以十进制转2进制 16进制转2进制 结果都是字符串 >>> bin(10) '0b1010' >>> bin(0x2) '0b10’ int 可以16进制转换十进制 2进制转换十进制 >>> int(0xe) 14 >>> int(0b100) 4
fromkeys(seq,value=None) 解释: 默认不写value的话,所有的值为None n = dict.fromkeys(['k1', 'k2'], []) #默认逗号后面不给的话,key对应的value都是None n['k1'].append(2) #我们修改逗号后面的空列表元素 打印 所有key的value也会修改 print(n) n['k1'] = 3 # 而单独修改key的value的话,只有 这个key的value改了,而其他的key对应的value都不变 print(n) n = dict.fromkeys() #默认逗号后面不给的话,key对应的value都是None print(n)
二、集合set:集合是一个无序且不重复的元素集合
s1={1,2,3,1} #定义一个set s1 如果s1={}为空则默认定义一个字典 s2=set([2,5,6]) #定义一个set s2 print(s1) #s1={1,2,3} 自动去除重复的元素 s1.add(5) #s1={1,2,3,5} 添加一个元素 print(s1) s3=s1.difference(s2) #返回一个s1中存在而不存在于s2的字典s3,s3={1,3},而s1并没有改变 print(s3) s1.difference_update(s2) #s1跟新成上面的s3 s1={1,3} s1.discard(1) #删除元素1,不存在的话不报错 s1={3} print(s1) s1.remove(3) #删除元素3,不存在的话报错 s1={} print(s1) s1.update([11,2,3]) #跟新s1中的元素,其实是添加 s1={11,2,3} print(s1) k=s1.pop() #删除一个元素,并将删除的元素返回给一个变量,无序的,所以并不知道删除谁 s1={1,2,3,4} #这里重新定义了集合s1,s2 s2={3,4,5,6} r1=s1.intersection(s2) #取交集,并将结果返回给一个新的集合 r1={3,4} print(r1) print(s1) s1.intersection_update(s2) #取交集,并将s1更新为取交集后的结果 s1={3,4} print(s1) k1=s1.issubset(s2) #s1是否是s2的的子序列是的话返回True,否则False 这里k1=true print(k1) k2=s1.issuperset(s2) #s1是否是s2的父序列 k2=False k3=s2.isdisjoint(s1) #s1,s2,是否有交集,有的话返回False,没有的话返回True print(k3) s1.update([1,2]) #s1={1,2,3,4} r3=s1.union(s2) #取并集将结果返回给r3 r3={1,2,3,4,5,6} print(r3) r2=s1.symmetric_difference(s2) #r2=s1并s2-s1交s2 r2={1,2,5,6} print(r2) s1.symmetric_difference_update(s2) #s1更新为 s1并s2 - s1交s2 s1={1,2,5,6} print(s1)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ a={1:2,4:5} b=set(a) b.add(111111) b.clear() print(b) n = {11,22,33} b = {22,66} c = {11} # n中有的b中没有的赋值给新的变量 打印 new_n = n.difference(b) print(new_n) #n中有的 b中没有的 更新到n # n.difference_update(b) # print(n) # 将迭代的序列加入 n.update("al") n.update([1,3,4]) print(n) #n存在的b不存在的 b存在n不存在的 组合一起输出 ret=n.symmetric_difference(b) ret2 = n.symmetric_difference({11,22,33}) print(ret) print("=========") # n存在的b不存在的 b存在n不存在的 组合一起 更新到前面的集合 n.symmetric_difference_update(b) print(n) # 是否是子集 不是返回false 是的话True ret = n.issubset(c) # n是不是c的子 print(ret) ret1 = c.issubset(n) # c是不是n的子 print(ret1) ret2 = n.issuperset(c) # n是不是c的父 print(ret2) # pop discard remove 三个删除的区别 #pop 删除同时可以获取到该值 ret = n.pop() #由于集合是无序的,所以pop删除也是无序的 print(ret) # discard 删除集合元素,如果元素不存在 返回False 不报错 n.discard(11) print(n) #remove 删除集合元素 如果元素不存在 报错 #n.remove(99) z = {11,22,33} p = {44} z.intersection(p) #取交集并更新到z中 print(z) 集合 练习 #!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' old_dict = { "#1":11, "#2":11, "#3":11, } new_dict = { "#1":33, "#4":22, "#7":100, } # b = set(old_dict.keys()) # print(b) s1 =set() s2 =set() for i in old_dict.keys(): s1.add(i) for n in new_dict: s2.add(n) print(s1,s2) ret1 = s1.difference(s2) print("for deling :",ret1) ret2 = s2.difference(s1) print("for adding:",ret2) # ret=s1.intersection(s2) # print(ret) for i in s1 : del old_dict[i] for i in s2: old_dict[i]=new_dict[i] print(old_dict)
a = set([1,2,3,4]) b = set([3,4,5,6]) a&b:求两个集合的交集--a.intersection(b) a|b--求两个集合的并集--a.union(b) a - b--求两个集合的差集--a.difference(b) a ^ b--求两个集合的对称差集--a.symmetric_difference(b) a.issubset(b)--a是b的子集 a.isuperset(b)--a是否包含b
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
交集 >>> a.append(10) >>> set(a) set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) >>> b =range(6) >>> a = set(a) >>> b =set(b) >>> a set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) >>> b set([0, 1, 2, 3, 4, 5]) 取交集 >>> a & b set([0, 1, 2, 3, 4, 5]) 交集应用场景:比如两个班级都叫alex或者两个班级都是100分的 或者两个班级中都大于多少分的 并集应用 >>> a | b set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) 差集 >>> a - b set([8, 9, 10, 6, 7]) 对称差集 >>> a - b set([8, 9, 10, 6, 7]) 把两个里面对方都没有的打印出来 A b 差集 a ^ b set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) >>> b set([0, 1, 2, 3, 4, 5, 12]) >>> a ^ b set([6, 7, 8, 9, 10, 11, 12]) a.add集合中添加一项,同样的去重不同样的增加 >>> a.add(0) >>> a.add(22) >>> a set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 22]) a.update集合添加多项 >>> a.update([23,34,35]) >>> a set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 34, 35, 22, 23]) 添加一个集合到另一个集合 >>> a.update(b) >>> a set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 34, 35, 22, 23]) #b.issubset(a) a.issuperset(b) 测试b中的每一个元素都在a中 >>> len(a) >>> len(b) >>> b in a False >>> a in a False >>> import tab >>> b.issubset(a) #测试b中的每一个元素都在a中 True >>> a.issubset(b) False >>> 3 in a True >>> b.issuperset(a) False >>> a.issuperset(b) #测试b中的每个元素都在a中 True
练习:寻找两个集合的差异
# 数据库中原有 old_dict = { "#1":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 80 }, "#2":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 80 } "#3":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 80 } } # cmdb 新汇报的数据 new_dict = { "#1":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 800 }, "#3":{ 'hostname':c1, 'cpu_count': 2, 'mem_capicity': 80 } "#4":{ 'hostname':c2, 'cpu_count': 2, 'mem_capicity': 80 } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # 数据库中原有 old_dict = { "#1":{ 'hostname':1, 'cpu_count': 2, 'mem_capicity': 80 }, "#2":{ 'hostname':1, 'cpu_count': 2, 'mem_capicity': 80 }, "#3":{ 'hostname':1, 'cpu_count': 2, 'mem_capicity': 80 } } # cmdb 新汇报的数据 new_dict = { "#1":{ 'hostname':1, 'cpu_count': 2, 'mem_capicity': 800 }, "#3":{ 'hostname':1, 'cpu_count': 2, 'mem_capicity': 80 }, "#4":{ 'hostname':2, 'cpu_count': 2, 'mem_capicity': 80 } } # b = set(old_dict.keys()) # print(b) s1 =set() s2 =set() for i in old_dict.keys(): s1.add(i) for n in new_dict: s2.add(n) new_jiaoji = s1.intersection(s2) print(new_jiaoji) for j in new_jiaoji: if old_dict[j] != new_dict[j]: print("need updating: { '%s': %s}"%(j,new_dict[j])) print(s1,s2) ret1 = s1.difference(s2) print("for deling :",ret1) ret2 = s2.difference(s1) print("for adding:",ret2) # ret=s1.intersection(s2) # print(ret) for i in s1 : del old_dict[i] for i in s2: old_dict[i]=new_dict[i] print(old_dict)
三、三元运算
python的三元运算:
变量名 = 变量1 if 条件判断成立 else 变量2
解释:条件成立 变量名值为变量1 否则为变量2
a=1 b=2 if a<b: #一般条件语句的写法 k=a else: k=b c=a if a<b else b #三目运算符的写法
四、深浅拷贝
拷贝意味着对数据重新复制一份,对于拷贝有两种深拷贝,浅拷贝两种拷贝,不同的拷贝有不同的效果。拷贝操作对于基本数据结构需要分两类进行考虑,一类是字符串和数字,另一类是列表、字典等。如果要进行拷贝的操作话,要import copy。
1、数字和字符串
对于数字和字符串而言,深拷贝,浅拷贝没有什么区别,因为对于数字数字和字符串一旦创建便不能被修改,假如对于字符串进行替代操作,只会在内存中重新生产一个字符串,而对于原字符串,并没有改变,基于这点,深拷贝和浅拷贝对于数字和字符串没有什么区别,下面从代码里面说明这一点
import copy s='abc' print(s.replace('c','222')) # 打印出 ab222 print(s) # s='abc' s并没有被修改 s1=copy.deepcopy(s) s2=copy.copy(s) #可以看出下面的值和地址都一样,所以对于字符串和数字,深浅拷贝不一样,数字和字符串一样就不演示了,大家可以去试一下 print(s,id(s2)) # abc 1995006649768 print(s1,id(s2)) # abc 1995006649768 print(s2,id(s2)) # abc 1995006649768
2、字典、列表等数据结构
对于字典、列表等数据结构,深拷贝和浅拷贝有区别,从字面上来说,可以看出深拷贝可以完全拷贝,浅拷贝则没有完全拷贝,下面先从内存地址分别来说明,假设 n1
=
{
"k1"
:
"wu"
,
"k2"
:
123
,
"k3"
: [
"alex"
,
456
]}
。
浅拷贝在内存中只额外创建第一层数据 深拷贝在内存中将所有的数据重新创建一
2.1、赋值:
赋值,只是创建一个变量,该变量指向原来内存地址,如:
n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]} n2 = n1
2.2浅拷贝
浅拷贝,在内存中只额外创建第一层数据
import copy n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]} n3 = copy.copy(n1)
2.3、深拷贝
深拷贝,在内存中将所有的数据重新创建一份(排除最后一层,即:python内部对字符串和数字的优化) 最底层数据要满足第一条赋值变量的条件
import copy n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]} n4 = copy.deepcopy(n1)
五、函数:函数传参,传的是引用
5.1 函数的定义:
- def:表示函数的关键字
- 函数名:函数的名称,日后根据函数名调用函数
- 函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...
- 参数:为函数体提供数据
- 返回值:当函数执行完毕后,可以给调用者返回数据。 注意是返回给函数调用者
5.2函数的参数:函数为什么要设置参数?
5.2.1无参函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def CPU报警邮件() #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 def 硬盘报警邮件() #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 def 内存报警邮件() #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 while True: if cpu利用率 > 90%: CPU报警邮件() if 硬盘使用空间 > 90%: 硬盘报警邮件() if 内存占用 > 80%: 内存报警邮件()
5.2.2有参函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def 发送邮件(邮件内容) #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 while True: if cpu利用率 > 90%: 发送邮件("CPU报警了。") if 硬盘使用空间 > 90%: 发送邮件("硬盘报警了。") if 内存占用 > 80%: 发送邮件("内存报警了。")
5.3函数参数的种类
- 普通参数
- 默认参数
- 动态参数
普通参数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# ######### 定义函数 ######### # name 叫做函数func的形式参数,简称:形参 def func(name): print name # ######### 执行函数 ######### # 'wupeiqi' 叫做函数func的实际参数,简称:实参 func('wupeiqi')
默认参数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def func(name, age = 18): print "%s:%s" %(name,age) # 指定参数 func('wupeiqi', 19) # 使用默认参数 func('alex') 注:默认参数需要放在参数列表最后
动态参数:
动态参数1:*args 是指可以传入多个参数用逗号隔开
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def func(*args): print args # 执行方式一 func(11,33,4,4454,5) # 执行方式二 li = [11,2,2,3,3,4,54] func(*li)
如果 元素参数是一个列表呢?我们把列表传入输出的一个元素是列表,但是我们想把列表的每个元素当一个参数。调用的时候加*
#!/usr/bin/env python # _*_ coding:utf-8 _*_ a=[1,3,4] def fuc(*args): #print(args) return args ret=fuc(a) print(ret) 结果: C:\Python35\python3.exe E:/py_test/s4/s5.py ([1, 3, 4],) #!/usr/bin/env python # _*_ coding:utf-8 _*_ a=[1,3,4] def fuc(*args): #print(args) return args ret=fuc(*a) print(ret) C:\Python35\python3.exe E:/py_test/s4/s5.py (1, 3, 4)
动态参数2:**kwargs 意指可以传入多个元素以key= value key的格式是按照变量名的命名规范为标准的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def func(**kwargs): print args # 执行方式一 func(name='wupeiqi',age=18) # 执行方式二 li = {'name':'wupeiqi', age:18, 'gender':'male'} func(**li)
如果 元素参数是一个字典呢?我们把列表传入输出的一个元素是字典,但是我们想把字典的每个key value当一个参数。调用的时候加** 只加*是key
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'liujianzuo' a={"k1":2,"k2":3} def fuc(**args): #print(args) return args ret=fuc(**a) print(ret) C:\Python35\python3.exe E:/py_test/s4/s5.py {'k1': 2, 'k2': 3}
动态参数3:*args **kwargs
def func(*args, **kwargs): print (args) print (kwargs)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ a={"k1":2,"k2":3} b=[1,2,3] def fuc(*args,**kwargs): #print(args) return args,kwargs ret=fuc(*b,**a) print(ret) C:\Python35\python3.exe E:/py_test/s4/s5.py ((1, 2, 3), {'k2': 3, 'k1': 2})
升级篇:邮件发送实例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # _*_ coding:utf-8 _*_ def email(p,text,subject): import smtplib from email.mime.text import MIMEText from email.utils import formataddr ret = True try: msg = MIMEText(text, 'plain', 'utf-8') msg['From'] = formataddr(["武沛齐",'wptawy@126.com']) msg['To'] = formataddr(["走人",'424662508@qq.com']) msg['Subject'] = subject server = smtplib.SMTP("smtp.126.com", 25) server.login("wptawy@126.com", "WW.3945.59") server.sendmail('wptawy@126.com', [p,], msg.as_string()) server.quit() except: ret = False return ret r1=email("1223995142@qq.com","python test email +===","subject==pyhon") if r1: print("发生成功") else: print("发送失败")
函数的变量:局部变量----全局变量
局部变量:针对某一个函数的内部的声明
全局变量:针对某一个.py文件,在文件的内部是有效的
age =28 #程序全局变量 def sayHi(name): age = 29 #函数局部变量 '''this is my first test function''' print ("hello %s,how are you?,my age is %s!") %(name,age) sayHi('mosson') print( 'age:',age)
让局部变量有全局变量的作用
更改方法;让局部变全局 global更改局部变全部 不建议使用 #age =28 def sayHi(name): global age age = 29 '''this is my first test function''' print("hello %s,how are you?,my age is %s!") %(name,age) sayHi('mososn') print ('age:',age)
作业:
1.普通参数,指定参数,默认参数,动态参数的区别
普通参数传递的个数和顺序要明确,默认参数传递的时候,如果没有给默认参数复制的话,会使用默认值,如果给定了的话,就会使用给定值。动态参数的个数不确定,可以传递任意个参数,这些参数自动组装成一个元组,可以在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去,指定参数传递的是一个明确的类似键值,这些参数自动组装成一个字典,可以先定义一个字典,在前面加上**变成关键字参数传给函数。
2.写函数计算传入的字符串中:数字、字母、空格以及其他的个数
def fun(s): digitnum, alphanum, sapcenum, othernum=0,0,0,0 for i in s: if i.isdigit(): digitnum+=1 elif i.isalpha(): alphanum+=1 elif i.isspace(): sapcenum+=1 else: othernum+=1 return (digitnum,alphanum,sapcenum,othernum)
3、写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5
def fun(s): ret=False if isinstance(s,str) or isinstance(s,str) or isinstance(s,tuple): if len(s)>5: ret=True return ret
4.写函数,检查用户传入的对象(字符串、列表、元组)的每一个元素是否含有空内容
def fun(s): ret=False if isinstance(s, str) or isinstance(s, str) or isinstance(s, tuple): for i in s: if i=='': ret=True break return ret