1. 迭代器
我们接触的迭代器通常指 序列:字符串 字典 列表 元组….迭代器可以理解为一个对数据的打包:
以下是几个迭代器的例子:
1.1.1 字符串的迭代:
for i in 'FISHC':
print(i)
1.1.2 字典的迭代:(字典迭代器里取出来的是键值key)
links ={'yhr':'ysp has a daughter',
'zwh':'zcg has a son',
'zyc':'yhr and zwh has a son'}
for i in links: #字典迭代器里取出来的是key
print("%s → %s"%(i, links[i]))
1.1.3 列表的迭代:
leibiao=[1,2,3,4,5]
for i in leibiao:
print(i,end=' ')
1.1.4 元组的迭代:
yuanzu = ('a','b','c')
for i in yuanzu:
print(i,end=' ')
1.2.1 迭代操作的两个bif:
iter() 得到容器对象的迭代器
next() 返回下一个值 如果没有下个值,就会抛出一个异常
string='yhr'
it=iter(string)
print(next(it))
print(next(it))
print(next(it))
# print(next(it)) #没有下个值,就会抛出一个StopIteration异常
那么我们对迭代器的for循环是不是可以由next和iter两个BIF实现呢?
↓
for 循环的迭代器实现:
string = 'zwh'
it = iter(string) #iter获取迭代器对象返回给it
while True:
try:
each = next(it)
except StopIteration: #没有next以后抛出stopIteration异常 捕捉异常 结束死循环
break
print(each)
1.2.2 两个魔法方法,注意不是BIF:
_ _ iter _ _() # 返回迭代器本身 return self
_ _ next _ _() # 决定了迭代器的迭代规则
例子:Fibonacci数列的实现:
class fibs:
def __init__(self):
self.a = 0
def __iter__(self):
print('iter......')
return self
def __next__(self):
print('next.....,', end=' ')
self.a , self.b = self.b, self.a+self.b
return self.a
fib=fibs()
for each in fib:
if each<20:
print(each)
else:
break
迭代器可以没有终点的运行下去
那么怎么控制迭代范围呢?
↓
由于For循环会自动处理stopIteraion的异常,所以可以在next里面设置抛出一个异常:
class fibs:
def __init__(self,n=10):
self.a = 0
self.b = 1
def __iter__(self):
print('iter......')
return self
def __next__(self):
print('next.....,', end=' ')
self.a , self.b = self.b, self.a+self.b
if(self.n<=0):
raise StopIteration #for 语句会处理StopIteration异常
else:
self.n-=1
return self.a
fib=fibs()
for each in fib:
print(each)
高铁上补笔记真的头昏眼花,先睡一觉再说吧咳咳咳
2. 生成器:
生成器 是迭代的一种方法,在普通的函数里加一个 yield 语句就可以实现生成器
模仿协同程序 ( 协同程序: 可以运行的独立函数调用,函数可以暂停或挂起,并在需要的时候从程序离开的地方继续或者重新开始 )
↓
生成器是一个特殊的函数,调用可以中断或者暂停,并且通过yield返回固定的值。
Eg:
def myGen():
print('生成器被执行!')
yield 1 # 相当于return 但是和普通函数不同,仅仅是暂停,返回完参数就继续执行
yield 2
myG = myGen()
print(next(myG))
print(next(myG))
# print(next(myG)) #StopIteration
倘若next里面没有值了,则会抛出stopIteration异常
↓
for循环可以处理StopIteration异常,所以以上程序我们可用for循环来实现:
myG = myGen()
for i in myG:
print(i)
例:Fibonacci数列的实现:
def fibs(countVal=5):
a = 0
b = 1
count = countVal
while True: #死循环
a , b = b , a+b
yield (a) # 每次yield都会暂停 返回一个a
count -=1
if(count<=0):
break #如果循环次数超过count(count默认为5)次,则跳出死循环
fib = fibs()
for i in fib:
print(i, end=' ')
3. 补充:推导式:
3.1 列表推导式:
Eg:求100以内 可以被2 整除,不能被3整除的数字:
a = [i for i in range(100) if not(i%2) and i%3]
print(a)
3.2 字典推导式:(字典需要冒号,否则就是集合)
Eg:求10以内被2 整除的情况:
b={i:i%2==0 for i in range(10)}
print(b)
3.3 集合推导式:(字典需要冒号,集合不需要冒号)
Eg:找出一个列表里可以被2整除的数字,组成一个集合:
c={ i for i in [1, 2, 2, 2, 2, 3, 3, 3, 6] if i%2==0 }
print(c)
字符串和元组没有推导式!
↓
比如假设元组存在推导式:
e=(i for i in range(3))
print(e)
3.4 其实是生成器推导式 generator object
↓
3.4.1. 生成器对象可以用next读取:
print(next(e), end =' ')
print(next(e), end =' ')
print(next(e), end =' ')
3.4.2. 也可以用集成好的for循环读取生成器对象:
for each in e:
print(each, end =' ')
↓
3.5 生成器推导式甚至可以作为函数参数:
例如求和:把从0 开始小于10的数字不能整除2的数字相加:
e = (i for i in range(10) if i%2)
for each in e:
print(each, end=' ')
print('\n',sum(i for i in range(10) if i%2)) #利用生成器对象作为函数参数