一.迭代器
写在前面 —— 可迭代对象
简单来说,能用for循环遍历的对象,都能称为可迭代对象,比如,列表(list), 集合(set),元组(tuple)等,可以使用for循环迭代的标志是内部实现了iter方法。
1.概念
简单来说迭代器是可以实现迭代过程的容器。可迭代对象一般只能按默认的正序方式进行迭代,你可以通过为其添加next()函数来定制不同的迭代方式,这样通过next()函数封装起来的迭代对象生成器就被称作迭代器。
2.创建
字符串,列表,集合都可以用于创建迭代器。
list = [1,2,3,4]
it = iter(list)
print(it) #输出<list_iterator object at 0x00000181562C0850>
print(next(it) #输出 1
print(next(it) #输出 2
'''
iter()函数是创造一个迭代器对象
next()函数是迭代出下一个元素
'''
创建一个迭代器
把一个类作为一个迭代器使用需要在类中实现两个方法 iter() 与 next() 。
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 5:
x = self.a
self.a += 1
return x
else:
raise StopIteration
myclass = MyNumbers()
myiter = iter(myclass)
for x in myiter:
print(x,end=" ") #输出 1 2 3 4 5
二.生成器
1.概念
在python中我们经常用列表来存储数据,但是受到内存容量的限制,列表的容量是有限制的,而且我们生成一个包含很多元素的列表,不仅会占用很多内存,如果我们只是需要列表中其中一小部分元素,那么剩下的元素占用的内存空间就会白白浪费。
所以,我们可以根据需要写算法推算出列表元素,在循环的过程中不断推算出后续元素,这样就不需创建完整list,从而节省大量的空间。在python中,这种一边循环一边计算的机制,称为生成器:generator。
1.创建
(1)方法1
把列表生成式中的中括号 [ ] 换成小括号 ( ) ,就创建了一个生成器。
demo
#创建列表
L = [x*x for x in range(10)]
print(L) #[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
print(type(L)) #<class 'list'>
#创建生成器
g = (x*x for x in range(10))
print(g) ##<generator object <genexpr> at 0x000002657D5A32E0>
print(type(g)) #<class 'generator'>
(2)方法2
利用关键字yield来创建生成器。
demo1 —— 普通实现斐波那契数列函数
def fb(max):
n,a,b=0,0,1
while n < max:
print(b,end='==')
a,b = b,a+b
n+=1
fb(10) #输出1==1==2==3==5==8==13==21==34==55==
'''
a,b=a,a+b相当于
t = (b, a + b) # t是一个tuple
a = t[0]
b = t[1]
'''
demo2 —— 实现斐波那契数列生成器
def fb(max):
n,a,b=0,0,1
while n < max:
yield b
a,b = b,a+b
n+=1
print (fb(10)) #
for i in fb(10):
print(i,end="==") #输出1==1==2==3==5==8==13==21==34==55==
注
带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator。调用 fb(10)的时候不会执行 fb 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fb 函数内部的代码,执行到 yield b 时,fb 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。
实战运用
展开
import requests
import re
import time
def get_one_page(url):
try:
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Edg/83.0.478.56"
}
r=requests.get(url,headers=headers)
if r.status_code==200:
print('ok')
return r.text
except RequestException:
return None
#获取排名,图片,电影名称,主演,发布时间,评分
def parse_one_page(html):
pattern = re.compile('<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)'
+'</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>'
+'(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>',re.S)
items = re.findall(pattern,html)
for item in items:
yield {
'排名':item[0],
'图片':item[1],
'电影名':item[2],
'主演':item[3].strip(),
'上映时间':item[4].strip(),
'评分':item[5]+item[6]
}
def main(offset):
url = 'http://maoyan.com/board/4?offset=' + str(offset)
html = get_one_page(url)
for item in parse_one_page(html):
print(item)
if __name__ == "__main__":
for i in range(10):
main(offset=i*10)
time.sleep(2)
参考 [Python 3网络爬虫开发实战 ,崔庆才著]