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)
1 2 3 4 5 6 | name = "李露" for i in name: print (i) #循环打印每个汉字而不是字节 bytes_list = bytes(i, encoding = 'utf-8' ) #将汉字转成字节,编码是utf-8 print (bytes_list) for b in bytes_list:<br> |
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
1 2 3 4 5 6 7 8 9 10 11 12 | 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:集合是一个无序且不重复的元素集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 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) |
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
#!/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)
1 2 3 4 5 6 7 8 | 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 |
交集 >>> 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
练习:寻找两个集合的差异
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 数据库中原有 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 } } |
#!/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
1 2 3 4 5 6 7 8 | a = 1 b = 2 if a<b: #一般条件语句的写法 k = a else : k = b c = a if a<b else b #三目运算符的写法 |
四、深浅拷贝
拷贝意味着对数据重新复制一份,对于拷贝有两种深拷贝,浅拷贝两种拷贝,不同的拷贝有不同的效果。拷贝操作对于基本数据结构需要分两类进行考虑,一类是字符串和数字,另一类是列表、字典等。如果要进行拷贝的操作话,要import copy。
1、数字和字符串
对于数字和字符串而言,深拷贝,浅拷贝没有什么区别,因为对于数字数字和字符串一旦创建便不能被修改,假如对于字符串进行替代操作,只会在内存中重新生产一个字符串,而对于原字符串,并没有改变,基于这点,深拷贝和浅拷贝对于数字和字符串没有什么区别,下面从代码里面说明这一点
1 2 3 4 5 6 7 8 9 10 11 | 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、赋值:
赋值,只是创建一个变量,该变量指向原来内存地址,如:
1 2 3 | n1 = { "k1" : "wu" , "k2" : 123 , "k3" : [ "alex" , 456 ]} n2 = n1 |
2.2浅拷贝
浅拷贝,在内存中只额外创建第一层数据
1 2 3 4 5 | import copy n1 = { "k1" : "wu" , "k2" : 123 , "k3" : [ "alex" , 456 ]} n3 = copy.copy(n1) |
2.3、深拷贝
深拷贝,在内存中将所有的数据重新创建一份(排除最后一层,即:python内部对字符串和数字的优化) 最底层数据要满足第一条赋值变量的条件
1 2 3 4 5 | 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无参函数
def CPU报警邮件() #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 def 硬盘报警邮件() #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 def 内存报警邮件() #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 while True: if cpu利用率 > 90%: CPU报警邮件() if 硬盘使用空间 > 90%: 硬盘报警邮件() if 内存占用 > 80%: 内存报警邮件()
5.2.2有参函数
def 发送邮件(邮件内容) #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 while True: if cpu利用率 > 90%: 发送邮件("CPU报警了。") if 硬盘使用空间 > 90%: 发送邮件("硬盘报警了。") if 内存占用 > 80%: 发送邮件("内存报警了。")
5.3函数参数的种类
- 普通参数
- 默认参数
- 动态参数
普通参数
# ######### 定义函数 ######### # name 叫做函数func的形式参数,简称:形参 def func(name): print name # ######### 执行函数 ######### # 'wupeiqi' 叫做函数func的实际参数,简称:实参 func('wupeiqi')
默认参数
def func(name, age = 18): print "%s:%s" %(name,age) # 指定参数 func('wupeiqi', 19) # 使用默认参数 func('alex') 注:默认参数需要放在参数列表最后
动态参数:
动态参数1:*args 是指可以传入多个参数用逗号隔开
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的格式是按照变量名的命名规范为标准的
def func(**kwargs): print args # 执行方式一 func(name='wupeiqi',age=18) # 执行方式二 li = {'name':'wupeiqi', age:18, 'gender':'male'} func(**li)
如果 元素参数是一个字典呢?我们把列表传入输出的一个元素是字典,但是我们想把字典的每个key value当一个参数。调用的时候加** 只加*是key
#!/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
1 2 3 4 | def func( * args, * * kwargs): print (args) print (kwargs) |
#!/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})
升级篇:邮件发送实例:
#!/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文件,在文件的内部是有效的
1 2 3 4 5 6 7 8 | 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) |
让局部变量有全局变量的作用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 更改方法;让局部变全局 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.写函数计算传入的字符串中:数字、字母、空格以及其他的个数
1 2 3 4 5 6 7 8 9 10 11 12 | 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
1 2 3 4 5 6 | 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.写函数,检查用户传入的对象(字符串、列表、元组)的每一个元素是否含有空内容
1 2 3 4 5 6 7 8 | 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 |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)
· 程序员常用高效实用工具推荐,办公效率提升利器!