Python - set & 函数
一、基本数据类型补充 ─ set(是一个无序且不重复的元素集合)
#创建集合,两种方式 >>> s = set([11,22,33]) #set 中最多传一个参数 >>> type(s) <#class 'set'> # 这里的#加上是为了显示,可以忽略 >>> new_s = {11,22,33} #用{},看起来像是字典,但是字典是有键值对,而set没有 >>> type(new_s) <#class 'set'>
#转换 >>> li = [11,22,33] >>> set(li) #讲列表转换为集合 {33, 11, 22} >>> li = [11,11,11] >>> set(li) #集合是不允许重复的,所以当列表li转为集合的时候,想的元素在集合中只显示一次 {11}
>>> s = set() #创建一个空集合 >>> s.add(11) #add只能添加一个元素,也不能添加列表,添加多个可以使用update >>> s {11}
>>> s = set() >>> s.update([11,22,33]) >>> s {33, 11, 22}
>>> s.clear() >>> s set()
>>> A = {11,22,33,44} >>> B = {11,33,55,77} >>> ret = A.difference(B) >>> A #A的数值不变 {33, 11, 44, 22} >>> ret #将A集合存在,B集合不存在的元素ret {44, 22}
>>> ret = A.difference_update(B) >>> A {22, 44} #A本身得到了变化 >>> ret >>> #ret是和空,这里就不会赋值给ret,而是赋值给了A
>>> A = {11,22,33,44} >>> B = {11,33,55,77} >>> ret = A.intersection(B) >>> ret {33, 11}
>>> A.intersection_update(B) >>> A {33, 11}
>>> A = {11,22,33,44} >>> B = {11,33,55,77} >>> ret = A.symmetric_difference(B) >>> ret {22, 55, 44, 77}
>>> A.symmetric_difference_update(B) >>> A {22, 55, 44, 77}
>>> A = {11,22,33,44} >>> B = {11,33,55,77} >>> ret = A.union(B) >>> ret {11, 77, 22, 33, 44, 55} #相同的元素只存一个,因为集合是不允许重复的
>>> A {22, 55, 44, 77} >>> A.discard(22) #从集合A中删除22 >>> A {55, 44, 77} >>> A.discard(99) #删除99,但是在集合中没有99,也没有报错
>>> A {55, 44, 77} >>> A.remove(77) #移除77,没问题 >>> A {55, 44} >>> A.remove(88) #移除88,在集合中不存在,报错 Traceback (most recent call last): File "", line 1, in KeyError: 88
>>> A = {11,22,33,44} >>> A.pop() #这里删除的为啥不是44呢?? 因为set是无序的, 33 >>> A {11, 44, 22}
>>> A = {11,22,33,44} >>> B = {11,33,55,77} >>> A.isdisjoint(B) False #A、B存在交集 >>> C = {56,7,8,4} >>> B.isdisjoint(C) True #B和 C完全不同,没有交集
>>> A = {11,22} >>> B = {11,22,33,44} >>> A.issubset(B) #A完全属于B,所以A是B的子集 True
>>> B.issuperset(A) True
二、三元运算
#普通 if 1 == 1: name = 'alex' else: name='durand' print(name) #三元运算 (减少代码量,只能做简单的if,else) name = 'alex' if 1 ==1 else 'durand' #name = 值1 if 条件 else 值2 print(name)
三、深浅拷贝
1.数字和字符串
对于 数字 和 字符串 而言,赋值、浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址。import copy # ######### 数字、字符串 ######### n1 = 123 # n1 = "i am alex" print(id(n1)) # ## 赋值 ## n2 = n1 print(id(n2)) # ## 浅拷贝 ## n3 = copy.copy(n1) print(id(n3)) # ## 深拷贝 ## n4 = copy.deepcopy(n1) print(id(n4))

2.其他基本数据类型
对于字典、元祖、列表 而言,进行赋值、浅拷贝和深拷贝时,其内存地址的变化是不同的。1)、赋值
赋值,只是创建一个变量,该变量指向原来内存地址,如:
n1 = {"name1": "Alex", "name2": 'Durand', "name3": ["Kevin", 19]} n2 = n1

2)浅拷贝,在内存中只额外创建第一层数据
import copy n1 = {"name1": "Alex", "name2": 'Durand', "name3": ["Kevin", 19]} n3 = copy.copy(n1)

3)深拷贝,在内存中将所有的数据重新创建一份(除了最后一层,即:python内部对字符串和数字的优化)
import copy n1 = {"name1": "Alex", "name2": 'Durand', "name3": ["Kevin", 19]} n4 = copy.deepcopy(n1)

四、函数
1)背景
在学习函数之前,一直遵循:面向过程编程,即:根据业务逻辑从上到下实现功能,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,也就是将之前实现的代码块复制到现需功能处,如下:while True: if cpu利用率 > 90%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 硬盘使用空间 > 90%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 内存占用 > 80%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接函数式编程,if条件语句下的内容可以被提取出来公用,如下:
def 发送邮件(内容) #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 while True: if cpu利用率 > 90%: 发送邮件('CPU报警') if 硬盘使用空间 > 90%: 发送邮件('硬盘报警') if 内存占用 > 80%:对于上述的两种实现方式,第二次必然比第一次的重用性和可读性要好,其实这就是函数式编程和面向过程编程的区别:
- 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
- 面向对象:对函数进行分类和封装,让开发“更快更好更强...”
2)定义和使用
def 函数名(参数): ... 函数体 ... 返回值函数的定义主要有如下要点:
- def:表示函数的关键字
- 函数名:函数的名称,日后根据函数名调用函数
- 函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...
- 参数:为函数体提供数据
- 返回值:当函数执行完毕后,可以给调用者返回数据。
函数是一个功能块,该功能到底执行成功与否,需要通过返回值来告知调用者。
以上要点中,比较重要有参数和返回值:
def 发送短信(): 发送短信的代码... if 发送成功: return True else: return False while True: # 每次执行发送短信函数,都会将返回值自动赋值给result # 之后,可以根据result来写日志,或重发等操作 result = 发送短信() if result == False: 记录日志,短信发送失败...002参数
def open_the_door(name): #定义函数的时候,这个name这个值为形式参数,他没有一个固定的数值,用来代替下面调用的时候需要传入的参数 return True if name == 'alex' else False ret = open_the_door('durand') #当调用函数的时候,需要传入一个参数与上面形参对应,如果有多个形参,也要传入对应个数的实参 print('开门') if ret else print('不开')
def drive(age,name = 'alex'): #如果传多个参数,且含默认参数,默认参必须数要放在后面 tmp = name +' 坐飞机' return tmp ret = drive(29,'durand') #如果传入name,将取代默认的alex ret1 = drive(19) #这里只需要传入一个数值给age print(ret,ret1)
def name(*a,**aa): # **aa 必须放在*a后面 print(a,type(a)) # *a为元组类型 print(aa,type(aa)) # **aa 为字典类型 name('alex','durand',name1='kevin',name2='Jin') def name(na,*a,**aa): # 传值的时候会把第一个参数传给na,剩下的传给 *a 与 **aa print(na,type(na)) print(a,type(a)) print(aa,type(aa)) name('alex','durand',name1='kevin',name2='Jin')
def name(*args): print(args,type(args)) li = ['alex','durand','kevin','Jin'] name(li) # 结果是 (['alex', 'durand', 'kevin', 'Jin'],)# 把li当作一个整体传进去了 name(*li) # 结果是 ('alex', 'durand', 'kevin', 'Jin') # 传值的时候,加上*,则是把列表的每个元素传进去
五、全局和局部变量
NAME = 'alex' #全局变量都用大写,可以被局部读取,不能修改,若修改需要使用global def name(): name = 'kevin' #局部变量都用小写,局部变量只能在局部被调用,出了这个函数就无法调用他 print(name) global NAME NAME = 'Jin' #如果没有使用global,这里创建的NAME 和全局的NAME是完全两个元素 print(NAME) def name2(): print(NAME) #调用全局NAME,看是否被更改成功 name() name2()
评论
发表评论