1、两个常用的迭代器内置函数
迭代:每一次迭代的结果被当作下一次迭代的初始值
迭代只是实现了next的一个对象,可以理解为具有指向下一项功能的指针
iter(),表示获取该函数的迭代器
next(),表示返回该迭代器的下一个值
也就是for循环实现迭代的原理
实例:
string = 'abcdefg'
it =iter(string)
next(it)
运行:
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
'd'
>>> next(it)
'e'
>>> next(it)
'f'
>>> next(it)
'g'
>>> next(it) #当到达迭代器的最后之后会返回一个StopIteration
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
next(it)
StopIteration
>>>
例如:用迭代器实现for循环 打印的功能
mylist = range(5)
it = iter(mylist) #获取函数mylist的迭代器(指针)
while True:
try:
print(next(it)) #返回该指针指向的下一个数据
except StopIteration:
break
2、相应的迭代器函数也对应着魔法方法
__iter__()
__next__()
1、用迭代器实现斐波那契数列的输出
class Fibs:
def __init__(self,n=10):
self.a = 0
self.b = 1
self.n =n
def __iter__(self):
return self
def __next__(self):
self.a,self.b = self.b,self.a+self.b
if self.a>self.n:
raise StopIteration
return self.a
运行:
>>> fibs =Fibs()
>>> for each in fibs:
print(each)
1
1
2
3
5
8
>>>
2、用迭代器实现闰年的输出
import datetime as dt
class LeapYear:
def __init__(self):
self.now = dt.date.today().year #调用datetime模块的函数返回当前的年份作为上限
def isLeapYear(self,year): #判断是否是闰年
if (year%4 ==0 and year%100 != 0) or (year%400==0):
return True
else:
return False
def __iter__(self): #表示获取类的实例的迭代器
return self
def __next__(self):
while not self.isLeapYear(self.now):
self.now -= 1
temp = self.now
self.now -=1
return temp
print(temp)
运行:
>>> for i in leapyear:
if i>=2000:
print(i)
else:
break
2016
2012
2008
2004
2000
3、用迭代器实现字符串翻转
class MyRev():
def __init__(self,data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def __next__(self):
if self.index ==0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
运行:
>>>myrev = MyRev()
>>>for i in myrev():
print(i)
二、生成器 generater
最大的作用是节约内存空间,如果一个很长的列表,如果每一个都显示出来存储就非常的占空间,此时利用生成器的原理,不算出来,而是将他存储在一个表达式里,需要时算出来。所以大部分时候生成器会和next()混在一起,但为了更简便,一般生成器是用for循环实现的。
g = (x * x for x in range(10))
for n in g:
print(n)
运行:
0
1
4
9
16
25
36
49
64
81
1、作用:yeild 控制程序中断挂起或者继续
如何理解yeild?相当于return和next()的混合
函数执行到yeild后,此时相当于return,也就是返回yeild后面的那个数,然后程序结束
当再次运行,比如next(),这一次开始的地方是接着上一次的停止的地方执行的。
def Mydemo():
print('我是生成器')
yield 1
print('我是第2步')
yield 2
>>> c = Mydemo()
>>> next(c)
我是生成器
1 #此时相当于一个return,返回1,结束。
>>> next(c) #next()程序继续从上次借宿的地方开始,打印出了我是第2步,接着又停在了yeild
我是第2步
2
>>> next(c)
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
next(c)
StopIteration
>>>
2、用生成器实现字符串翻转
def myRev(data):
for index in range(len(data)-1,-1,-1): #range的范围是[len(data)-1,-1],每次减少的步长是1
yield data[index] #相当于return data[index]
运行:
>>> for i in myRev('today'): #这个for循环打印myRev里面全部的字符
print(i,end = '')
yadot
def libs():
a = 0
b = 1
while True:
a,b = b,a+b
yield a #生成器将值返回至a并暂停
>>> for each in libs():
if each >100:
break
print(each,end=' ')
1 1 2 3 5 8 13 21 34 55 89
>>>
2、生成器的推导式
扫描二维码关注公众号,回复:
9622163 查看本文章
a = [i for i in range(50) if not (i%2) and i%3] #列表推导式
print(a)
b = {i:i%2==0 for i in range(5)} #字典推导式
print(b)
c = (i for i in range(10)) #生成器推导式,not 元组推导式
print(c)
[2, 4, 8, 10, 14, 16, 20, 22, 26, 28, 32, 34, 38, 40, 44, 46]
{0: True, 1: False, 2: True, 3: False, 4: True}
<generator object <genexpr> at 0x0000026B995A7F48>
>>> next(c)
0
>>> next(c)
1
>>> next(c)
2
>>> next(c)
3
>>> next(c)
4
>>> next(c)
5
>>> next(c)
6
>>>
3、用生成器实现素数求和
import math
def is_prime(number): #判断是否是素数
if number > 1:
if number == 2:
return True
if number % 2 == 0:
return False
for current in range(3, int(math.sqrt(number) + 1), 2): #超快判断素数
if number % current == 0:
return False
return True
return False
def get_primes(number): #往无限增大的方向,一个一个获取判断出的素数
while True:
if is_prime(number):
#这里如何实现循环?
#其实这类问题你在yield语句前后加几个标记点就明白了。如下补充
yield number
number += 1
def solve(): #求和
total = 2
for next_prime in get_primes(3):
if next_prime < 2000000:
total += next_prime
else:
print(total)
return
if __name__ == '__main__':
solve()
运行:
142913828922
#关于判断如何循环,加一个打印
def get_primes(number):
while True:
if is_prime(number):
print('标点三')
yield number
print('标点四')
number += 1
def solve():
total = 2
for next_prime in get_primes(3):
if next_prime < 10:
total += next_prime
else:
print(total)
return
print('第一次循环结束')
运行:
标点三 #1、solve里面的for循环,第一次循环时,get_primes(3)会跳到get_primes函数,打印标点三
第一次循环结束 #2、在get_primes里面的if成立时,执行yield number之后,程序会返回到solve里面的for循环中调用它的地方,继续循环,直至循环结束
标点四 #3、在for循环的第一次循环结束之后,程序会跳回yield number这里,然后才开始执行number += 1,后面依次继续循环
标点三
第一次循环结束
标点四
标点三
第一次循环结束
标点四
标点三
17