本文内容:
一、文件操作
二、函数
三、locals() 和 globals()
四、迭代器
五、高阶函数
5.2 reduce(func,Iterable) 计算数据
5.3 filter(func,Iterable) 过滤数据
5.4 sorted(Iterable , reverse=False , key = 函数)
六、推导式
七、生成式
一 .文件操作
对文件操作流程
- 打开文件,得到文件句柄并赋值给一个变量
- 通过句柄对文件进行操作
- 关闭文件
文件内容可以写入:1.字节流 2.字符串
1.基本操作
# 1.打开文件 fp = open("lianxi.txt",mode="w",encoding="utf-8") # 2.写入文件 fp.write("把大象塞进去") # 3.关闭文件 fp.close()
# 1.打开文件 fp = open("lianxi.txt",mode="r",encoding="utf-8") # 2.读取文件 res = fp.read() # 3.关闭文件 fp.close() print(res)
2.字节流操作
二进制字节流的应用场景: 在数据传输或者在数据存储时,使用的一种数据格式;
多个字符放在一起叫做字符串,多个字节放在一起叫做字节流;
将字符串和字节流(Bytes流)类型进行转换 (参数写成转化的字符编码格式)
encode() 编码 :将字符串转化为字节流(Bytes流)
decode() 解码 :将Bytes流转化为字符串
字节流的格式:字节流语法格式(前面加b) : b"123"
strvar = b"123" strvar = b"abc" # 中文不能在字符串前面加b,必须是ascii编码才能加; # strvar = b"你好" error print(strvar , type(strvar)) # b'123' <class 'bytes'>
中文和字节流的转化
# encode 编码 strvar = "我爱你".encode("utf-8") print(strvar) # decode 解码 res = strvar.decode("utf-8") print(res) # 三个字节表达一个中文字符 s_bytes = b'xe7x88xb1' res = s_bytes.decode("utf-8") print(res)
文件中写入字节流
"""mode = wb 代表写入的是字节流 , 不要指定任何编码集 """ # 1.打开文件 fp = open("lianxi2",mode="wb") strvar = "爱上一匹野马,家里没有草原" # 2.写入字节流 fp.write(strvar.encode()) # 3.关闭文件 fp.close()
从文件中读字节流
"""mode = rb 代表读取的是字节流 , 不要指定任何编码集 """ # 1.打开文件 fp = open("lianxi2",mode="rb") # 2.读取字节流 res = fp.read() # 3.关闭文件 fp.close() print(res) print(res.decode())
小例子:模拟复制图片的过程
1 # 打开原文件,读取其中的字节流 2 fp = open("集合.png",mode="rb") 3 res = fp.read() 4 fp.close() 5 print(res) 6 7 # 把这些字节流写入到另外文件中 8 fp = open("集合2.gif",mode="wb") 9 fp.write(res) 10 fp.close()
总结: 二进制字节流比如:图片,音频,视频 ... 数据使用二进制字节流进行拷贝
3.文件的扩展模式
read() 功能: 读取字符的个数(里面的参数代表字符个数)
seek() 功能: 调整指针的位置(里面的参数代表字节个数)
seek(0) 把光标移动到文件开头
seek(0,2) 把光标移动到文件末尾
tell() 功能: 当前光标左侧所有的字节数(返回字节数)
1..r+ 先读后写
fp = open("lianxi.txt",mode="r+",encoding="utf-8") # 先读 res = fp.read() # 后写 fp.write("456") # 在读 fp.seek(0) #因为文件指针在文件末尾,指向开头 res = fp.read() print(res) fp.close()
2.r+ 先写后读
r+模式打开后 文件指针默认指向文件的开头,马上写入内容,会覆盖原有的内容
fp = open("lianxi.txt",mode="r+",encoding="utf-8") # 先写 fp.seek(0,2) # 打开文件后默认指向文件开头 fp.write("789") # 后读 fp.seek(0) res = fp.read() print(res) fp.close()
3.w+ 可写可读
w+模式打开文件后,首先默认清空文件,所以先读后写没有意义;
fp = open("lianxi2.txt",mode="w+",encoding="utf-8") # 先写 fp.write("123") # 后读 fp.seek(0) print(fp.read()) fp.close()
4.a+ 可写可读
a+模式打开后 文件指针默认指向文件的末尾,所以可以直接写入内容
fp = open("lianxi3.txt",mode="a+",encoding="utf-8") fp.write('abc') fp.seek(0) print(fp.read()) fp.close()
5.比对a+和r+两个模式之间的区别
r+模式下 写入内容时,会随着光标位置的改变而替换原有的字符
a+模式下 写入内容时,会强制把光标移动到文件的末尾
6.seek ,read , tell 三个方式的使用
read(单位) 单位根据文件打开的模式而产生变化,如果带有b模式,读取的是字节的个数,否则读取的是字符的个数
在移动seek时,小心光标移动到中文字符里,在读取内容时,产生无效的开始字节
fp = open("lianxi.txt",mode="r+",encoding="utf-8") fp.seek(6) res = fp.tell() #6 print(res) res = fp.read(3) print(res) res = fp.tell() print(res) fp.close()
7. with语法 (上下文管理器)可以省略掉close操作
with open("ceshimv.mp4",mode="rb") as fp1 , open("ceshimv2.mp4",mode="wb") as fp2: res = fp1.read() fp2.write(res)
4.文件相关的方法
1.刷新缓冲区 flush
刷新缓冲区有一下几种情况
(1). 当文件关闭的时候自动刷新缓冲区
(2).当整个程序运行结束的时候自动刷新缓冲区
(3)当缓冲区写满了 会自动刷新缓冲区
(4)手动刷新缓冲区
2.文件相关函数
1.readable() 功能: 判断文件对象是否可读
2.writable() 功能: 判断文件对象是否可写
3.readline() 功能 :读取文件一行内容
(1) .先读取一行,如果内容不是空,打印这行数据,在读取下一行进行判断
with open("lianxi.txt",mode="r",encoding="utf-8") as fp: res = fp.readline() while res: print(res) res = fp.readline()
(2).readline(2) 2个字符个数
如果读取个数 > 当前行总个数 : 按照当前行读取
如果读取个数 < 当前行总个数 : 按照个数读取
4.readlines 功能:将文件中的内容按照换行读取到列表当中
5.writelines() 功能:将内容是字符串的可迭代性数据写入文件中 参数:内容为字符串类型的可迭代数据
6.truncate() 功能: 把要截取的字符串提取出来,然后清空内容将提取的字符串重新写入文件中 (字节)
with open("lianxi4.txt",mode="r+",encoding="utf-8") as fp: fp.truncate(9)
二.函数
1.函数基本格式
定义函数 def 函数名(): code1 code2... 调用函数 函数名()
2.函数的命名
字母数字下划线,首字符不能为数字;
严格区分大小写,且不能使用关键字;
函数命名有意义,且不能使用中文哦;
1.驼峰命名法:
(1)大驼峰命名法:mycar => MyCar 每个单词首字符大写 (面向对象中 => 类)
(2)小驼峰命名法: mycar => myCar 除了第一个单词首字符小写外,剩下的每个单词首字符大写 (用在函数中 .. )
2.命名法: 单词和单词之间用_分开 mycar => my_car
3.函数的参数
函数的参数的种类: 1.形参 2.实参
1.形参: 形式上的参数,在函数的定义处
2.实参: 实际上的参数,在函数的调用处
形参种类: 1.普通形参(位置形参) 2.默认形参 3.普通收集形参 4.命名关键字形参 5 关键字收集形参
实参种类: 1.普通实参 2.关键字实参
1.普通形参
"""hang,lie是普通形参(位置形参)""" def func(hang,lie): i = 0 while i < hang: j = 0 while j < lie : print("*" ,end="") j += 1 print() i += 1 # 调用函数 """10,10是普通实参""" func(10,10) func(3,8)
2.默认形参
hang=10,lie=10 是默认形参,如果给与了实参,那么使用实参值,如果没有给与实参,那么使用默认值
def func(hang=10,lie=10): i = 0 while i < hang: j = 0 while j < lie : print("*" ,end="") j += 1 print() i += 1 # 调用函数 # func() func(5) # func(4,6)
3.普通形参 + 默认形参
hang普通形参,lie=10默认形参
注意点:默认形参必须跟在普通形参的后面
def func(hang,lie=10): i = 0 while i < hang: j = 0 while j < lie : print("*" ,end="") j += 1 print() i += 1 # func(5) func(5,6)
4.关键字实参
关键字实参的顺序可以任意颠倒
注意点: 关键字实参必须写在普通实参的后面
def func(hang,a,b,c,lie=10): i = 0 while i < hang: j = 0 while j < lie : print("*" ,end="") j += 1 print() i += 1 func(3,4,b=5,lie=7,c=6)
区别关键字实参和默认形参:
1.在def定义处,使用的参数是默认形参
2.在函数的调用处,使用的参数是关键字实参
5.普通收集参数
功能: 专门用来收集那些多余的没人要的普通实参
语法: 在参数的前面加上一颗星
返回: 一个元组
def func(a,b,c,*args): print(a,b,c) #1 2 3 print(args) # (43,44) func(1,2,3,43,44)
计算任意个数值的累加和
1 def func(*args): 2 print(args) # (1, 2, 3, 4, 5, 6, 7) 3 total = 0 4 for i in args: 5 total += i 6 print(total) 7 8 func(1,2,3,4,5)
6.关键字收集参数
功能: 专门用来收集那些多余的没人要的关键字实参
语法: 在参数的前面上加上二颗星星
返回: 一个字典
def func(a,b,c,**kwargs): print(a,b,c) # 1 4 3 print(kwargs) #{'f': 5, 'z': 10, 'x': 30} func(a=1,c=3,f=5,b=4,z=10,x=30)
做任意个数值的字符串拼接
1 """ 2 颜值担当: 李雅琪 3 靓丽女生: 王永捐 4 普通颜值: 于盛林, 荷叶 , 吴洪昌 5 """ 6 7 def func(**kwargs): 8 strvar1 = '' 9 strvar2 = '' 10 dic = {"beautiful_boy":"颜值担当" , "beautiful_girl":"靓丽女生"} 11 print(kwargs) # {'beautiful_boy': '李雅琪', 'beautiful_girl': '王永捐', 'common1': '于盛林', 'common2': '荷叶', 'common3': '吴洪昌', 'first': '菲菲', 'last': '石磊'} 12 for k,v in kwargs.items(): 13 # print(k,v) 14 # 如果该键在dic当中,说明是预定义角色,要获取该角色是什么 : 颜值担当 靓丽女生 15 if k in dic: 16 # 颜值担当 : 李雅琪 + ' ' 17 # 靓丽女生 : 王永捐 + ' ' 18 strvar1 += dic[k] + ":" + v + ' ' 19 else: 20 # 于盛林, 荷叶, 吴洪昌, 菲菲, 石磊, 21 strvar2 += v + "," 22 23 24 print(strvar1.strip()) 25 print( "普通颜值:" , strvar2.strip(",") ) 26 27 func(beautiful_boy = "李雅琪",beautiful_girl="王永捐",common1="于盛林",common2="荷叶",common3="吴洪昌",first="菲菲",last="石磊")
7 命名关键字形参
如果是命名关键字形参 , 在调用函数时,必须使用关键字实参的方式调用
(1) def func(a,b,*,c,d) 在星号后面定义的是命名关键字形参
def func(a,b,*,c,d): print(a,b) print(c) print(d) func(1,2,c=3,d=4)
(2) def func(*args,c,**kwargs) 在普通收集和关键字收集形参之间的是命名关键字形参
print("<=========>") def func(*args,c,**kwargs): print(args) print(c) print(kwargs) func(1,2,3,4,45,a=1,b=2,c=3)
8.* 和 ** 的使用方法
(1) 在定义处: 负责收集打包数据
* : 负责收集打包成元组
**: 负责收集打包成字典
(2) 在调用处: 负责打散解包数据
* : 负责对list tuple str set 打散解包成单独的数据
**: 负责对dic 打散解包成单独的键=值的形式
# 函数的定义处 def func(a,b,*,c,d): print(a,b) print(c,d) lst = [1,2] # 打散之后,把列表里面的元素一个个拿出来作为函数的参数进行调用 tup = (1,2) set1 = {"aaa","bbb"} str1 = "ab" dic = {"aaaa":1,"bbbb":2} # 获取的是字典的键 # 函数的调用处 一颗星 *可迭代数据前面 func(*dic,c=3,d=4) # func(1,2,c=3,d=4) # 函数的调用处 二颗星 **只能在字典前面修饰; dic = {"c":3,"d":4} func(1,2,**dic) # 把字典打散,抽离其中的键值对,变成 => c=3,d=4 关键字实参,作为参数调用函数;
函数的参数定义顺序:
普通形参(位置形参) => 默认形参 => 普通收集形参 -> 命名关键字形参 -> 关键字收集形参;
4.return
return : 会把函数内部的值返回到函数的调用处;
(1)return后面可以接 6大标准数据类型 ,还可以接函数,类,对象,如果没有自定义返回值,默认返回的None
(2)执行完return之后,函数直接终止,后面的代码不执行;
5.全局变量 和 局部变量
局部变量: 在函数内部定义的变量是局部变量
全局变量: 在函数外部或者在函数内部使用global定义的变量是全局变量
作用域: 作用的范围
局部变量: 在函数的内部
全局变量: 横跨整个文件
生命周期:变量存活的时间
内置变量 > 全局变量 > 局部变量
1.局部变量
def func(): # 创建一个局部变量 a = 1 # 获取局部变量 print(a) # 修改一个局部变量 a = 10 print(a) func() # print(a) error
2.全局变量
方法一 :在函数外部定义的是全局变量
# 创建一个全局变量 b = 100 # 获取全局变量 print(b) # 修改全局变量 b = 299 print(b) def func(): # 全局变量可以直接在函数内部调用 print(b) func()
方法二: 在函数内部定义全局变量,依赖global
def func(): # 声明一个全局变量c global c # 创建一个全局变量 c = 99 func() print(c)
# 在函数内部修改全局变量 d = 200 def func(): global d d = 300 func() print(d) #300
global总结:
如果函数外部没有该全局变量,那么可以通过global在函数内部直接创建一个全局变量
如果函数外部有该全局变量,那么可以通过global在函数内部修改当前全局变量
6.函数名的使用
python中的函数可以像变量一样,动态创建,销毁,当参数传递,作为值返回,作为容器中的元素.叫第一类对象.其他语言功能有限
1 # 1.动态创建 2 def func(): 3 print("我是func1 ... ") 4 print(type(func)) 5 a = 1 6 print(type(a)) 7 a = func 8 a() 9 10 # 2.动态销毁 11 del a 12 # a() error 13 # func() 14 15 # 3.当参数传递 16 def func1(f): 17 f() 18 19 def func2(): 20 print("我是func2 ... ") 21 22 func1(func2) 23 24 # 4.作为值返回 25 def func1(f): 26 return f 27 28 def func3(): 29 print("我是func3 ...") 30 res = func1(func3) 31 res() 32 33 # 5.可以把函数作为容器中的元素 34 def func1(): 35 print("我是func1 .. ") 36 def func2(): 37 print("我是func2 .. ") 38 def func3(): 39 print("我是func3 .. ") 40 lst = [func1,func2,func3] 41 for i in lst: 42 i() 43 44 45 # ### __doc__ 用来查看帮助文档 46 def wash(something): 47 48 """ 49 功能: 洗衣服的过程 50 参数: something => 衣服 51 返回值: 洗完的状态 52 """ 53 54 print( "先脱{}".format(something) ) 55 print("放在桶里") 56 print("到点洗衣液") 57 print("泡水,搓一搓") 58 print("穿上~") 59 return "洗完了" 60 61 wash("衣服") 62 63 # __doc__ 函数.__doc__ 获取函数内部自定义文档; 64 res = wash.__doc__ 65 print(res)
7.函数的嵌套
互相嵌套的两个函数:
外层函数即外函数
内层函数即内函数
def outer(): inner() def inner(): print("我是内函数 ... ")
(1)内部函数不可以直接在函数外部调用
(2)调用外部函数后,内部函数不可以在函数外部调用
(3)内部函数可以在函数内部调用吗
(4)内部函数在函数内部调用时,必须先定义函数,在调用函数,没有预加载机制
三层函数嵌套,最外层是outer,中间层是inner ,最里层 smaller , 调用smaller函数
def outer(): def inner(): def smaller(): print("我是smaller函数 ... {}".format(id)) smaller() inner() outer() print(outer)
LEGB 就近找变量原则:
找寻变量的调用顺序采用LEGB原则(即就近原则)
B —— Builtin(Python);Python内置模块的命名空间 (内建作用域)
G —— Global(module); 函数外部所在的命名空间 (全局作用域)
E —— Enclosing function locals;外部嵌套函数的作用域(嵌套作用域)
L —— Local(function);当前函数内的作用域 (局部作用域)
依据就近原则,从下往上 从里向外 依次寻找
8.nonlocal (修改局部变量)
nonlocal 专门用来修改局部变量,符合LEGB原则,就近找变量,
(1).找当前作用域上一层空间的变量值进行修改
def outer(): a = 1 def inner(): nonlocal a a = 10 print(a) #10 inner() print(a) #10 outer()
(2).如果上一层不存在,继续向上一层空间进行寻找
def outer(): a = 199 def inner(): a = 201 def smaller(): nonlocal a a = 200 print(a) #200 smaller() print(a) #200 inner() print(a) #199 outer()
(3).直到最后找不到,直接报错
a = 199 # 是全局变量, 而nonlocal用来修改局部变量; def outer(): def inner(): def smaller(): nonlocal a a = 200 print(a) smaller() print(a) inner() print(a) outer()
不通过 nonlocal 可以修改局部变量
def outer(): lst = [10,20,30] def inner(): lst[0] = 100 inner() print(lst) #[100, 20, 30] outer()
9、闭包函数
互相嵌套的两个函数,内函数使用了外函数的局部变量,
外函数把内函数返回出来的过程,叫闭包,内函数叫做闭包函数
原则:
(1) 内函数使用了外函数的局部变量
(2) 外函数将内函数返回return
1.闭包函数基本语法
def liyaqi_family(): father = "李嘉诚" def hobby(): print("我对钱没有兴趣,我只对捐钱感兴趣,这是我爸爸{}说的".format(father)) return hobby res = liyaqi_family() res()
2.闭包的复杂语法
1 def liangruiqing_family(): 2 jiejie = "马蓉" 3 meimei = "马诺" 4 money = 1000 5 6 def jiejie_hobby(): 7 nonlocal money 8 money -= 600 9 print("喜欢出轨,喜欢花钱,喜欢买包包,手表,GUCCI,chanel...家里的钱败光了,还剩下{}".format(money)) 10 11 def meimei_hobby(): 12 nonlocal money 13 money -= 399 14 print("我就喜欢在宝马里面哭,不喜欢在自行车上面撒欢~...家里的钱败光了,还剩下{}".format(money)) 15 16 def big_master(): 17 return [jiejie_hobby,meimei_hobby] 18 19 # def func(): 20 # print(jiejie) 21 # return func 22 23 return big_master 24 25 26 func = liangruiqing_family() 27 # 获取姐姐函数 28 jiejie = lst[0] 29 jiejie() #家里的钱败光了,还剩下400 30 # 获取妹妹函数 31 meimei = lst[1] 32 meimei() 家里的钱败光了,还剩下1
3.闭包的特点
互相嵌套的两个函数形成了闭包;内函数使用了外函数的局部变量,
该变量与内函数发生绑定,延长该变量的生命周期,直到该脚本运行结束.
def outer(val): def inner(num): return val + num return inner func = outer(10) res = func(5) print(res) #15
4.闭包的意义
在做计数加1的过程当中,发现全局变量的值范围太大,导致可以被任意篡改,数据不安全
clicknum = 0 def func(): global clicknum clicknum += 1 print(clicknum) func() func() func() clicknum = 100 func() #101
出现的问题:单纯的局部变量不能累加1,
def clicknum(): x = 0 x += 1 print(x) clicknum() clicknum() clicknum()
闭包的意义:
闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.外部无法访问
def clicknum(): x = 0 def func(): nonlocal x x += 1 print(x) return func func = clicknum() # func = 闭包函数func func() func() x = 100 func() #3
10.匿名函数
用一句话来表达只有返回值的函数叫做匿名函数
语法: lambda 参数 : 返回值
(1)无参的匿名函数
def func(): return "我是func1111" res = func() print(res) # lambda 改造 func = lambda : "我是func1111" print(func())
(2) 有参的匿名函数
def func(num): return type(num) res = func([1,2,3]) print(res) # lambda 改造 func = lambda num : type(num) print(func({"a":"1",'b':2}))
(3) 带有判断条件的匿名函数
三元(目)运算符 (只能在双向分支上可以使用,单项多项都不行)
语法: 真值 if 条件表达式 else 假值 => 如果条件表达式是真的,返回真值,否则返回假值
def func(num): if num % 2 == 0: return "偶数" else: return "奇数" res = func(11) print(res) # lambda 改造 print("<=================>") func = lambda num : "奇数" if num % 2 == 1 else "偶数" print(func(102))
三.locals() 和 globals()
1.locals() 获取当前作用域的变量
在函数外,获取的是打印之前所有全局变量
在函数内,获取的是调用之前所有局部变量
# 1.在函数外 a = 1 b = 2 dic = locals() c = 3 print(dic) #a b c 都要打印
# 2.在函数内 def func(): a = 1 b = 2 dic = locals() c = 3 print(dic) d = 4 f = 5 func() # #打印 a b g = 6
2 . globals() 获取全局变量
在函数外,获取的是打印之前所有全局变量
在函数内,获取的是调用之前所有全局变量
# 1.在函数外 a = 1 b = 2 dic = globals() c = 3 print(dic) ## a b c 都要打印
# 2.在函数内 def func(): a = 1 b = 2 dic = globals() c = 3 print(dic) d = 4 f = 5 func() ## 只打印 f g = 6
3 .利用globals批量创建全局变量
globals实现,通过字符串创建一个全局变量
globals返回的是系统内置的一个字典
通过往内置字典中添加键值对,实现全局变量的创建
dic = globals() # 通过往内置字典中添加键值对,实现全局变量的创建 dic["wangwen"] = "王文" print(dic) print(wangwen) #"王文"
四、迭代器
迭代器:能被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator 迭代器是对象)
概念:迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复都是基于上一次的
结果而继续的,单纯的重复并不是迭代
特征:并不依赖索引,而通过next指针(内存地址寻址)迭代所有数据,一次只取一个值,
而不是一股脑的把所有数据放进内存.大大节省空间
1、 可迭代性对象
如果一个对象中含有__iter__这个成员,说明该数据是可迭代性对象;
ps:查看该对象中的成员,dir
setvar = {"白金鸽","杨特","郝建康"} # 查看该对象中的成员,dir lst = dir(setvar) if '__iter__' in lst: print("该数据是可迭代性数据") print(lst)
2、 迭代器
如果是迭代器,一定是可迭代对象
如果是可迭代对象,不一定是迭代器;
1.如何变成一个迭代器
setvar = {"白金鸽","杨特","郝建康"} # 1.如何变成一个迭代器 it = iter(setvar) # 方法一 it = setvar.__iter__() # 方法二 lst = dir(it) print(lst)
2.如何判断一个迭代器 __iter__ + __next__
if "__iter__" in lst and "__next__" in lst: print("该数据是迭代器")
3.如何调用一个迭代器
1 # 方法一 2 res = next(it) 3 print(res) 4 res = next(it) 5 print(res) 6 res = next(it) 7 print(res) 8 # res = next(it) error 9 # print(res) 10 11 # 4.重置迭代器 12 it = iter(setvar) 13 # res = next(it) 14 res = it.__next__() 15 print(res) 16 17 # 方法二 18 print("<=========>") 19 for i in it: 20 print(i) 21 # next(it) error 单项不可逆的过程 22 23 # 方法三 24 print("<=========>") 25 setvar = {"白金鸽","杨特","郝建康","于盛林","杨业","王娟娟","草配线","孟凡伟"} 26 it = iter(setvar) # setvar.__iter__() 27 for i in range(8): 28 print(next(it))
五、高阶函数
高阶函数 : 能够把函数当成参数传递的就是高阶函数
1、map(func,Iterable) : 处理数据
功能:
把Iterable中的数据一个一个的传递到func函数当中进行处理,处理之后的结果通过迭代器一个一个获取
参数:
func:内置或者自定义函数
Iterable : 可迭代性数据(容器类型数据 range对象 迭代器)
返回值:
迭代器
# (1) ["1","2","3","4"] => [1,2,3,4] lst = ["1","2","3","4"] lst_new = [] for i in lst: # print(int(i)) lst_new.append(int(i)) print(lst_new) # 使用map改写 it = map(int,lst) for i in it: print(i,type(i)) print(list(it))
# (2) [1,2,3,4] => [5,10,15,20] lst = [1,2,3,4] lst_new = [] for i in lst: res = i * 5 lst_new.append(res) print(lst_new) # 使用map改写 """ 注意点 : 参数和返回值必不可少""" def func(n): print(1111111111) return n * 5 it = map(func,lst)
2、reduce(func,Iterable) 计算数据
功能:
先把Iterable中的前两个数据拿出来,扔到func中做处理,得出一个结果,
在拿当前结果和Iterable的下一个值在继续扔到func做计算,
依次类推...
直到最后返回结果.
参数:
func : 自定义函数
Iterable : 可迭代性对象(容器类型数据 , range对象 , 迭代器)
返回值:
计算最后的结果
#(1) [5,4,8,8] => 5488 from functools import reduce def func(x,y): return x*10 + y lst = [5,4,8,8] res = reduce(func,lst) print(res,type(res)) # lambda 改造 print(reduce( lambda x,y : x*10 + y , lst))
# (2) "5488" => 5488 不让使用int函数 def func(x,y): return x*10 + y def func2(n): dic = {} for i in range(10): dic[str(i)] = i return dic[n] # 功能: "5488" => 5,4,8,8 it = map(func2,"5488") # 功能: [5,4,8,8] => 5488 res = reduce(func,it) print(res , type(res))
3、filter(func,Iterable) 过滤数据
功能:
通过自定函数的返回值控制当前数据保留与否
return True 代表保留
return False 代表舍弃
参数:
func : 自定义的函数
Iterable : 可迭代性数据(容器类型数据,range对象,迭代器)
返回值:
迭代器
# lst = [1,12,435,234,122,2] => 过滤掉偶数,保留奇数 lst = [1,12,435,234,122,2] lst_new = [] for i in lst: if i % 2 == 1: lst_new.append(i) print(lst_new) # 使用filter进行改造 def func(n): if n % 2 == 1: return True else: return False it = filter(func,lst) lst = list(it) print(lst) # 使用lambda 进行改造 print(list(filter( lambda n : True if n % 2 == 1 else False , lst )))
4、sorted(Iterable , reverse=False , key = 函数)
功能:
排序数据
参数:
Iterable : 可迭代对象 (容器类型数据 range对象 迭代器)
reverse : 正序或者倒序 reverse = False (从小到大)
key : 内置或者自定义方法
返回值:
排序后的数据(列表)
# 1.从小到大 lst = [-9,18,13,16,99,87] res = sorted(lst) print(res) # 2.从大到小 res = sorted(lst,reverse=True) print(res)
sort 和 sorted的区别:
[sorted] 推荐
1.sorted 可以对所有的容器类型数据排序
2.返回一个新的列表
[sort]
1.sort 只能对列表这一个类型进行排序
2.针对于原有的列表进行排序
六 、推导式
概念: 通过一行循环判断,遍历出一系列数据的方法就是推导式
推导式种类三种:
[val for val in Iterable] 列表推导式
{val for val in Iterable} 集合推导式
{a:b for a,b in iterable} 字典推导式
1.列表推导式
1.单循环推导式基本语法
# 创建列表,内容为1~50 lst = [ i for i in range(1,51) ] print(lst)
2.带有判断条件的单循环推导式
注意点: 在循环后面只能跟单项分支
# 1 ~ 100 中的所有偶数保留到列表里 lst = [] for i in range(1,101): if i % 2 == 0 : lst.append(i) print(lst) # 改写推导式 lst = [ i for i in range(1,101) if i % 2 == 0 ] print(lst
3.多循环推导式基本语法
lst1 = ["于盛林","荷叶","王永娟"] lst2 = ["李琦","朱培峰","刘灵镇"] lst = [] for i in lst1: for j in lst2: lst.append(i + "♠" + j) print(lst) # 改写推导式 lst = [ i + "♠" + j for i in lst1 for j in lst2 ] print(lst)
4.带有判断条件的多循环推导式
lst = [] for i in lst1: for j in lst2: if lst1.index(i) == lst2.index(j): lst.append(i + "♠" + j) print(lst # 改写推导式 lst = [ i + "♠" + j for i in lst1 for j in lst2 if lst1.index(i) == lst2.index(j) ] print(lst)
2.集合推导式
""" 案例: 满足年龄在18到21,存款大于等于5000 小于等于5500的人, 开卡格式为:尊贵VIP卡老x(姓氏),否则开卡格式为:抠脚大汉卡老x(姓氏) 把开卡的种类统计出来 """ data = [ {"name":"李琦","age":22,"money":20000}, {"name":"李雅琪","age":19,"money":12000}, {"name":"吴洪昌","age":18,"money":5300}, {"name":"王召","age":80,"money":4000}, {"name":"王生父","age":81,"money":5400} ] setvar = set() for i in data: if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500: strvar = "尊贵VIP卡老{}".format(i["name"][0]) else: strvar = "抠脚大汉卡老{}".format(i["name"][0]) # 把对应的开卡格式存入到集合当中 setvar.add(strvar) print(setvar) # 改写成集合推导式 # 三运运算符 + for循环 => 集合推导式 setvar = { "尊贵VIP卡老{}".format(i["name"][0]) if 18 <= i["age"] <= 21 and 5000 <= i["money"] <= 5500 else "抠脚大汉卡老{}".format(i["name"][0]) for i in data } print(setvar)
3.字典推导式
(1)enumerate
enumerate(iterable,[start=0])
功能: 枚举 ; 将索引号和iterable中的值,一个一个拿出来配对组成元组,通过迭代器返回
参数:
iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range)
start: 可以选择开始的索引号(默认从0开始索引)
返回值: 迭代器
lst = ["欢庆","尤佳","刘文波","黄长剑"] it = enumerate(lst) # 默认从0开始索引 it = enumerate(lst,start=1) # start = 1表示从1开始枚举配对;
# 1.配合enumerate完成字典推导式操作 dic = { k:v for k,v in enumerate(lst) } print(dic) # 2.直接通过dict强转 dic = dict(enumerate(lst)) print(dic)
(2)zip(iterable, ... ...)
功能: 将多个iterable中的值,一个一个拿出来配对组成元组,通过迭代器返回
iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range)
返回: 迭代器
原则: zip的配对原则会按照相同的索引组合,如果没有相同的索引自动舍弃;
# 1.配合zip完成字典推导式操作 lst_key = ["zy","sxy","jyh"] lst_val= ["张印","孙翔宇","家营和"] dic = { k:v for k,v in zip(lst_key,lst_val) } print(dic) # 2.直接通过dict强转 dic = dict(zip(lst_key,lst_val)) print(dic)
七、生成器
生成器本质是迭代器,允许自定义逻辑的迭代器
迭代器和生成器区别:
迭代器本身是系统内置的.重写不了.而生成器是用户自定义的,可以重写迭代逻辑
生成器可以用两种方式创建:
(1)生成器表达式 (里面是推导式,外面用圆括号)
(2)生成器函数 (用def定义,里面含有yield)
1、生成器表达式
# 生成器表达式 gen = (i for i in range(100)) print(gen) # generator # 调用生成器 # 1.next res = next(gen) print(res) # 2.for + next (推荐) for i in range(3): print(next(gen)) # 3.for (慎用,防止数据量较大时,形成类似于死循环的效果) # for i in gen: # print(i) # 4.list (慎用,防止数据量较大时,内存溢出,出现蓝屏) lst = list(gen) print(lst)
2、生成器函数
yield 类似于 return
共同点在于:执行到这句话都会把值返回出去
不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走
而return直接终止函数,每次重头调用.
1.生成器函数语法
def mygen(): print("one") yield 1 print("two") yield 2 print("three") yield 3 # 初始化生成器函数 => 返回生成器对象 , 简称生成器 gen = mygen() res = next(gen)
2.生成器优化写法
def mygen(): for i in range(1,101): yield "新制造的篮球球衣号码是{}".format(i) # 初始化生成器函数 => 返回生成器对象 , 简称生成器 gen = mygen() # 先获取前30个数据 for i in range(30): print(next(gen))
3.send语法的使用
send send发送值的时候,是给上一个yield
next和send区别:
next 只能取值
send 不但能取值,还能发送值
send注意点:
第一个 send 不能给 yield 传值 默认只能写None
最后一个yield 接受不到send的发送值
1 def mygen(): 2 print("start ... ") 3 res = yield "111" 4 print(res) 5 6 res = yield "222" 7 print(res) 8 9 res = yield "333" 10 print(res) 11 12 res = yield "444" 13 print(res) 14 print("end ... ") 15 16 # 初始化生成器函数 => 返回生成器对象 , 简称生成器 17 gen = mygen() 18 # 第一次发送数据时,无脑加None 19 res = gen.send(None) 20 print(res) 21 res = gen.send("我来了老妹2") 22 print(res) 23 res = gen.send("我来了老妹3") 24 print(res) 25 res = gen.send("我来了老妹4") 26 print(res) 27 # res = gen.send("我来了老妹5") error 28 # print(res)
4. yield from 的基本使用
yield from : 将一个可迭代对象变成一个迭代器返回
def mygen(): # yield [1,2,3,4,5] yield from [1,2,3,4,5] gen = mygen() print(next(gen)) print(next(gen)) print(next(gen)) print(next(gen))
5、斐波那契函数(生成器)
def fib(max): a,b = 0 , 1 i = 0 while i < max: # print(b) yield b a,b = b,a+b i += 1 gen = fib(10) for i in range(5): print(next(gen))