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()
评论
发表评论