标签:ali 第一个 字典 eve 移动 return 参数 dir break
一、迭代器
可以通过下面方法来证明(也可以用该方法判断变量的数据类型)
li=[11,2,3,4,5]
dic={‘key1‘:‘a‘,‘key2‘:‘b‘}
print(isinstance(li,list))#True
print(isinstance(dic,dict))#True
#元组和集合就不一一证明了
num=12345
print(isinstance(num,Iterable))#False
这说明字典列表,元组,集合是可迭代对象,数字类型不是
可迭代的:内部必须含有一个__iter__方法
print(dir([1,2,3]))
print(dir(2,4,5))
print(dir{‘key‘:‘value‘})
print(dir{1,2,3})
#以上输出的结果中都含有__inter__方法
迭代器优点:节约内存、不依赖索引取值、实现惰性计算
迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。
两种迭代器
1.可迭代对象通过执行iter方法得到:使用__iter__()方法
li=[‘a‘,‘b‘,‘c‘,‘d‘]
iterator=li.__iter__() #将可迭代的转化成迭代器
item=iterator.__next__()# 取列表的第一个数据a
print(item)#输出:列表中的第一个数据a
item=iterator.__next__()# 取列表的第二个数据b
print(item)#输出:列表中的第二个数据b
2.调用方法直接返回:使用iter()返回迭代器本身next()返回容器的下一个元素
li=[‘a‘,‘b‘,‘c‘,‘d‘]
iterrator=iter(li) # 将可迭代的转化成迭代器
print(next(iterator))#a
print(next(iterator))#b
print(next(iterator))#c
如果不再有下一个元素的话程序会抛出异常,通过捕获异常来处理
li=[‘a‘,‘b‘,‘c‘,‘d‘]
iterrator=iter(li) # 将可迭代的转化成迭代器
while True:
try:
print(iterrator.__next__())
except:
break
#输出:
a
b
c
d
for循环的底层逻辑:
1.将可迭代对象转化成迭代器
2.内部使用__next__方法,一个一个取值
3.加了异常处理功能,取值到底后自动停止
二、生成器
能实现迭代器功能的就叫生成器,其本质是迭代器
生成器自带了__iter__方法和__next__方法
def genrator():
a=1
print(‘现在定义的a变量‘)
yield a
b=2
print(‘现在又定义了b变量‘)
yield b
g=genrator()
print(g)#打印g可以发现g就是一个生成器
print(g.__next__())
print(‘--------‘)
print(g.__next__())
#输出:
<generator object genrator at 0x0154DDF0>
现在定义的a变量
1
--------
现在又定义了b变量
2
也可以用next()来写
def genrator():
a = 1
print(‘现在定义了a变量‘)
yield a
b = 2
print(‘现在又定义了b变量‘)
yield b
g = genrator()
print(next(g))
print(next(g))
#输出:
现在定义了a变量
1
现在又定义了b变量
2
通过使用生成器,不会让内存中生成大量数据。
我们可以通过这个例子来理解一下:假如我想让工厂给生产面包,生产20000个面包,我和工厂一说,工厂应该是先答应下来,然后再去生产,我可以一个一个的要,也可以根据学生人数的多少,一批一批的拿。而不能是一说要生产20000个面包,工厂就先去做生产20000个面包,等把工厂把20000个做好了,前面生产的面包就已经过期了
def bread():
for i in range(1,20000):
yield "生产了%s个面包"%i
Bread=bread()
print(Bread.__next__())#要一个面包
print(Bread.__next__())#再要一个面包
print(Bread.__next__()) #再要一个面包
#要一批面包50件
num=0
for i in Bread:
print(i)
num++
if num==50:
break
def generator():
print(123)
args=yield 1
print(‘send传的参数是%s‘%args)
print(456)
yield 2
g=generator()
ret=g.__next__()
print(ret)
ret=g.send(‘聚焦教育‘)
print(ret)
#输出:
123
1
send传的参数是聚焦教育
456
2
send()方法说明:
1.send 获取下一个值的效果和next基本一致
2.只是在获取下一个值的时候,给上一yield的位置传递一个数据
使用send的注意事项:
1. 第一次使用生成器的时候 是用next获取下一个值
2. 最后一个yield不能接受外部的值
生成器函数应用实例:移动平均值
def mean():
sum=0
count=0
val=0
while True:
num=yield val
sum+=num
count+=1
val=sum/count
g=mean()
next(g)
ret=g.send(15)
print(ret)
ret=g.send(20)
print(ret)
列表推导式
li=[i for i in range(10)]
print(li)#[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
li=[‘选项%s‘%i for i in range(10)]
print(li)#[‘选项0‘, ‘选项1‘, ‘选项2‘, ‘选项3‘, ‘选项4‘, ‘选项5‘, ‘选项6‘, ‘选项7‘, ‘选项8‘, ‘选项9‘]
例一:10以内所有能被2整除的数
li=[i for i in range(10) if i%2==0]
print(li)#[0, 2, 4, 6, 8]
例二:20以内所有能被3整除的数的平方
def func(x):
return x*x
ret=[func(i) for i in range(20) if i%3==0]
print(ret)#[0, 9, 36, 81, 144, 225, 324]
例三:找到嵌套列表中名字含有两个‘e’的所有名字
name_list = [‘Jim‘, ‘Boos‘, ‘Jeen‘, ‘Andrew‘, ‘Wesley‘, ‘Steven‘, ‘Joe‘]
ret=[i for i in name_list if i.count(‘e‘)>=2]
print(ret)#[‘Jeen‘, ‘Wesley‘, ‘Steven‘]
names = [[‘Jim‘, ‘Boos‘, ‘Jeen‘, ‘Andrew‘, ‘Wesley‘, ‘Steven‘, ‘Joe‘],
[‘Alice‘, ‘Jill‘, ‘Ana‘, ‘Wendy‘, ‘Jennifer‘, ‘Sherry‘, ‘Tom‘]]
ret=[name for lst in names for name in lst if name.count(‘e‘)>=2]
print(ret)#[‘Jeen‘, ‘Wesley‘, ‘Steven‘, ‘Jennifer‘]
字典推导式
例一:将一个字典的key和value对调
dic = {‘a‘: 6, ‘b‘: 8}
ret={dic[k]:k for k in dic}
print(ret)#{6: ‘a‘, 8: ‘b‘}
例二:合并大小写对应的value值,将k统一成小写
dic = {‘a‘: 11, ‘b‘: 22, ‘A‘: 33, ‘Z‘: 44}
dic_ret={k.lower():dic.get(k.lower(),0)+dic.get(k.upper(),0)for k in dic.keys()}
print(dic_ret)
#{‘a‘: 44, ‘b‘: 22, ‘z‘: 44}
集合推导式
set1={x**2 for x in[1,2,3,4]}
print(set1)
#{16, 1, 4, 9}
大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议
例:计算一系列值的和
ret=sum(x**2 for x in range(3))
print(ret)#5
标签:ali 第一个 字典 eve 移动 return 参数 dir break
原文地址:https://www.cnblogs.com/peng-blogs/p/14556603.html