迭代器与生成器,装饰器,推导式
可迭代对象(iteration)
遵守可迭代对象的协议 具有__iter__()方法
print(dict.__iter__({‘i’:1}))
除去整型和布尔值剩下现已知都是
迭代器(iterator): 遵守迭代器的协议 具有__iter__()方法和__next__()方法
创建一个迭代器 == 可迭代对象.iter()
使用迭代器 == 迭代器.next()
迭代器:不能回退,惰性机制,一次性的
for循环的机制 两种方式
生成器
生成器可以暂时挂起函数,并保留函数的局部变量等数据,然后在再次调用它的时候,从上次暂停的位置继续执行下去。
1.
lst = [1,2,3,4,5]
count = 0
l = lst.__iter__()
while count < len(lst):
print(l.__next__())
count += 1
2.
lst = [1,2,3,4,5,67,7]
l = lst.__iter__()
while True:
try: # 异常捕获
print(l.__next__())
except StopIteration:
break
s = '123'.__iter__()
s1 = s.__iter__()
print(s1.__next__())
print(s.__next__())
怎么查看是迭代器还是可迭代对象:
from collections import Iterator,Iterable
print(isinstance([1,2,3],Iterable)) # 查看是否是可迭代的
print(isinstance('查看的内容',Iterator)) # 查看是否是迭代器
加上__.iter__()就是迭代器
生成器
定义
函数体中存在yield就是生成器,函数+()就产生 生成器
_next__ 和 yield 要一一对应, 最后的一个yield下边能写就是不运行
生成器是迭代器,具有迭代器的可迭代和使用next()函数的功能。记住:生成器是一种特殊的迭代器
三、为什么要使用生成器函数,而不是直接使用函数
1、通过列表生成式可以直接创建一个列表,但是受到内存的限制,可能创建一个很大的空间,但是实际情况中用不到那么多(在C语言中所谓的堆区,没释放)
2、生成器(generator)的定义就是根据列表元素可以动态的分配内存空间
3、在实际开发过程中,如果我们要读取一个十几G大的文件,如果是直接使用文件打开的方式,其实底层的全部加载在内存中,这样造成计算机内存消耗,造成计算机卡死的局面,如果我们使用生成器,把大文件做成文档碎片的方式,每次从中间读取一点出来,然后再释放内存,这样就不会对计算机造成卡死的局面。
def foo():
print(1)
n = yield 2
print(n)
print(3)
yield 4
g = foo()
print(g) #<generator object foo at 0x0000026218165AF0>
print(g.__next__())
print(g.send(66))
结果:1 2 66 3 4
send() 发送 send() == next + 传值
send()传递给上一个yield的
最后的一个 yield 下边的可以写代码,但是执行不到
第一次启动这个生成器的时候 生成器.next 或 生成器.send(None)
生成器的好处
节省空间
可以for去执行这个生成器直接打印i就行,for的本身就是一直的__next__
yield from 调用的时候只能使用__next__()啊
推导式
1)列表推导 a=[结果 for I in 可迭代对象]
li = [i for i in range(10) if i>4]
2)字典dic={k:v for k,v in 可迭代}
dic={'a':'b','c':'d'}
d={k:c for k,c in dic.items()}
print(d)
3)集合s=set{结果 for I in 可迭代对象}
lst=['a','c']
lst1=['b','d']
d={lst[i]:lst1[i] for i in range(2)}
print(d)
4)生成器s=(结果 for I in 可迭代对象) 长得像元祖
l=(i for i in range(100))
for i in range(10):
print(l.__next__())
装饰器
1.本质就是闭包
开放封闭原则
扩展开发,修改源代码封闭,不能修改调用方式
在不改源代码的基础上添加功能
@装饰器的名字 在被装饰的函数正上方 独占一行
@语法糖 被装饰的函数名 = 装饰器的名字(被装饰的函数名)
3,python装饰器的应⽤场景装饰器的应⽤场景
1,引⼊⽇志
2,函数执⾏时间统计
3,执⾏函数前预备处理
4,执⾏函数后清理功能
5,权限校验等场景
6,缓存
7,事务处理
在 Flask 或 Django 框架中,用于路由函数或视图函数上,以实现权限控制、日志记录等功能。
在测试框架中,用于标记测试用例或测试函数,以设置断言、超时等条件。
在日志系统中,用于记录函数的入参和出参,以便调试和分析程序的行为。
在性能分析工具中,用于统计函数的执行时间或内存占用情况。
在缓存系统中,用于缓存函数的计算结果,以提高程序的执行效率
2.装饰器作用:
在不改变函数调用方式的基础上添加一些功能
3.functools.wraps的作用
保留原有函数的名称(消除装饰器带来的副作用)
简单写一个装饰器
import time
def timer(func):
def inner(*args,**kwargs):
start = time.time()
re = func(*args,**kwargs)
print(time.time()-start)
return re
return inner
@timer #==> func1 = timer(func1)
def func1(a,b):
print('in func1')
@timer
def func2(a):
print('in func2 and get a:%s'%(a)) #n func2 and get a:cccc
return 'func2 over'
func1('aaa','bbbb') #in func1
print(func2('cccc')) #i func2 over
有参装饰器
内置函数
all()可迭代对象中都为真才是真
方法一:
size = "lg"
color = "blue"
price = 50
# bad practice
if size == "lg" and color == "blue" and price < 100:
print("Yes, I want to but the product.")
方法一:size = "lg"
color = "blue"
price = 50
bad practice
if size == "lg" and color == "blue" and price < 100:
print("Yes, I want to but the product.")
方法二:
conditions = [
size == "lg",
color == "blue",
price < 100,
]
if all(conditions):
print("Yes, I want to but the product.")
Any()可迭代对象中有一个为真就是真
any用法同上
callable判断是否可调用
print(pow(2,3)) 求幂
print(pow(2,3,3)) 求幂后再取余
print(round(3.332324,3)) #四舍五入 第一个参数是浮点数 第二参数的要保留的小数位
1.lambda匿名函数
语法:lambda 参数:返回值
定义:lambda 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的函数。
lambda函数有什么好处?
lambda函数比较轻便,即用即仍;
匿名函数,一般用来给filter,map这样的函数式编程服务;
作为回调函数,传递给某些应用,比如消息处理
匿名函数没有名字,怎么查看 函数.name
匿名函数的返回值只能是一个,不能是多个
匿名函数可不可以写到一行
print((lambda x,y:x+y)(3,6))
print((lambda x:x)()) 调用的时候要传参
def func(n):
return n**n
print(func(4))
等同于下:
f = lambda x: x**x
print(f(4))
写上end='\n'和不写end是换行,end=''是两个连在一起
print('bjk','hjb',sep=' |') #sep默认是空格
print('mk','jjnk',end='')
repr显示数据原生
例:1)和函数组合使用
定义一个列表,然后根据一元素的长度排序
lst = ['天龙八部','西游记','红楼梦','三国演义']
def func(s):
return len(s)
print(sorted(lst,key=func))
结果:
['西游记', '红楼梦', '天龙八部', '三国演义']
2)和lambda组合使用:
lst = ['天龙八部','西游记','红楼梦','三国演义']
print(sorted(lst,key=lambda s:len(s)))
2.sorted()
sorted :内置函数 排序
语法:sorted(iterable,key=None,reverse=False)
sorted('可迭代对象',key='函数名(函数名里写排序规则),reverse=True的时候是降序')
print(sorted(lst))
例子:使用sorted()函数来按照字典的value来对其进行排序
d = {
"v1": 80,
"v2": 20,
"v3": 40,
"v4": 20,
"v5": 10,
}
sorted_d = dict(sorted(d.items(), key=lambda item: item[1]))
print(sorted_d)
当然我们也可以使用itemgetter( )来替代上述 lambda函数,代码如下:
from operator import itemgetter
sorted_d = dict(sorted(d.items(), key=itemgetter(1)))
3. filter()过滤
函数可以是匿名,也可以是定义好的,得有判断条件
语法: filter(function,iterable)
dic=[{'a':'d','s':15},{'d':'k','s':1}]
print(list(filter(lambda x:x['s']>5,dic)))
4.map() 映射函数,累加
语法: map(function,iterable)
一个列表中每个元素的平方
print(list(map(lambda x:x**2,lst)))
5.zip() 拉链
将对象中对应的元素打包成一个个元祖,返回的是对个,如果有三个可迭代对象,就按照最短的进行输出#4.
lst1 = [1,2,3]
lst2 = ['a','b','c','d']
lst3 = (11,12,13,14,15)
for i in zip(lst1,lst2,lst3):
print(i)
结果:
(1, 'a', 11)
(2, 'b', 12)
(3, 'c', 13)
6.enumerate(lst,10) #枚举
将可迭代对象放到里边,默认数字是0开始,自己指定开始的数字
li = ['x','a','sd']
for i,e in enumerate(li,10):
print(i,e)
结果
"""
10 x
11 a
12 sd
"""
7.reduce 累计算 从python3中引入
语法:reduce(函数名,可迭代对象) # 这两个参数必须都要有,缺一个不行
第一次的时候 x是1 y是2 x乘以10就是10,然后加上y也就是2最终结果是12然后临时存储起来了
第二次的时候x是临时存储的值12 x乘以10就是 120 然后加上y也就是3最终结果是123临时存储起来了
第三次的时候x是临时存储的值123 x乘以10就是 1230 然后加上y也就是4最终结果是1234然后返回了
from functools import reduce
lst=[1,5,3]
print(reduce(lambda x,y:x*y,lst))
递归:
递 函数调用
归 函数的返回值
1)1.自己不断调用自己本身 -- 1,死递归
2.有明确的终止条件 -- 1,2 才是有效递归
2) 默认深度是1000 实际测试998
修改深度 import sys
import sys
sys.setrecursionlimit('修改的数量')
递归的应用: 文件查看 创建文件,删除文件
总结
迭代器:
具有 iter 和 next 的就是迭代器
生成器一定是一个迭代器,迭代器不一定是生成器
具有 iter 和 next,send 的就是生成器
区别
1.生成器和迭代器的区别:
迭代器必须是定义了__iter方法和__next方法的对象.它每次调用时会返回自身的下一个元素,比传统方式节省内存;
生成器是一次生成一个值的特殊类型的函数, 调用该函数将返回一个可用于生成连续某值的生成器.
生成器和迭代器应用场景
读取(获取)较大的文件和内容的时候使用,防止内存溢出