参考了《Python3从入门到实战》
一、迭代器
1.一个可迭代的队象的__iter()方法返回一个迭代器,而这个迭代器的__next()方法会返回可迭代对象的下一个元素
注:可迭代对象可以用for in 来进行输出,而迭代器要用next方法()
2.Python提供了两个对应的内置函数iter() 和 next() ,内置函数iter()作用于可迭代对象,会调用这个对象的__iter__()方法返回一个迭代器,而内置函数next()作用于这个迭代器,会调用这个的带起的__next()__方法返回可迭代元素的下一个元素
alist = [1,3,5,19,7]
it = iter(alist)#返回一个迭代器
print(type(alist))
print(type(it))
print(next(it))#得到迭代器的下一个值
运行结果如下:
<class 'list'>
<class 'list_iterator'>
1
下列的类A实现了__iter__()方法,因此类A的对象就是一个可迭代对象,iter()的方法必须返回一个迭代器,即B类的对象必须是一个迭代器,也就是说类B必须实现__next__()方法
import time
class A(object):
def __iter__(self):
return B()
class B(object):
def __next__(self):
return "hello"
iterable = A()#可迭代对象 可迭代对象由下列方法进行迭代
iterator = iter(iterable)#迭代器 迭代器用next方法
#一直打印hello
i = 0
for e in iterable:
print(e)
time.sleep(1)
print(i)
i += 1
运行结果如下:
hello
0
hello
1
hello
2
hello
3
hello
#需要自己按下停止按钮,这里没有设置什么时候停止,而是一个死循环
class A(object):
def __iter__(self):
return B()
class B(object):
def __init__(self):
self.i = 0
self.data = [2,4,8]
def __next__(self):
if self.i == 3:#计数,到3就停止执行
raise StopIteration()
self.i += 1
return self.data[self.i-1]#返回每个值
iterable = A()
for e in iterable:
print(e,end=" ")
运行结果如下:
2 4 8
3.通常,可迭代对象的所属类和迭代器的所属类并不是这样完全分离的,而是同一个类,这个类同时实现__iter__()和__next__()方法,因此这类的对象即使一个可迭代对象也是一个迭代器
class X(object):
def __init__(self):
self.i = 0
self.data = [2,4,8]
def __iter__(self):
return self
def __next__(self):
if self.i == 3:
raise StopIteration()
self.i += 1
return self.data[self.i-1]
b = X()
it = iter(b)#得到迭代器
print(next(it))
#print(next(it))
b2 = X()
for i in b2:
print(i)
运行结果如下:
2
2
4
8
4.一个对象是可迭代的,除其所属类实现__iter__()方法,其所属类还可以实现__getitem__()方法
5.如果用for循环将输出无限循环,其第二个参数是一个键(关键字),对实现该方法的类对象obj,可以通过obj[key]来得到该键对应的值
class Y:
def __getitem__(self,i):
return i * i
y = Y()
print(y[2])
运行结果如下:
4
class MyDict:
def __init__(self):
self.dict = {
}
def __getitem__(self,key):
return self.dict[key]
def __setitem__(self,key,value):
self.dict[key] = value
def __len__(self):
return len(self.dict)
d = MyDict()
d['李萍'] = 67.5#调用setitem方法
print(d['李萍'])#调用getitem方法
d['王伟'] = 77.5
print(d['王伟'])
运行结果如下:
67.5
77.5
二、生成器
1.生成器是一个用于创建迭代器的简单而强大的工具,又是一个可以产生一系列值的函数,生成器会记住上一次执行的语句,每当需要数据时,生成器都会从中断处继续,并通过yield语句产生一新的数据.因此生成器是一个特殊的迭代器,也是一个可迭代对象
生成器函数
def gen(n):
for i in range(n):
yield(i)
'''生成器会记住函数执行的状态,当再次调用__next__()方法时,
会根据上次的位置和状态,继续执行,当再次遇到yield语句,
又产生一个新的返回值并终止当前的执行.
'''
g = gen(5)
print(g.__next__())
print(g.__next__())
print(next(g))#也可以用这种方法(因为生成器也是迭代器)
print(g)#g是一个生成器的对象
print(type(g))
#迭代
g = gen(10)#生成器是一个可迭代对象
for i in g:
print(i)
运行结果如下:
0
1
2
<generator object gen at 0x000002335EEF0A50>
<class 'generator'>
0
1
2
3
4
5
6
7
8
9
2.包含return的函数当遇到return语句时,会停滞函数执行并返回,函数每次执行都是独立的,且是从头开始的,不会保存上一次执行的状态和位置
3.包含yield的生成器函数用于产生一系列值,每次执行当遇到yield语句会停止执行,并返回yield语句的结果,但内部会保留上一次执行的状态,下一次执行从上一次执行的yield之后的代码继续执行,直到再次遇到yield返回
4.生成器函数可以用来生成一系列的值,这些值没有保存的内存中,而是在需要的时候产生,这样可以节省很多内存
#求1到10的整数和
#生成器方法
def gen(n):
for i in range(n):
yield i
g = gen(11)#这是一个生成器
sum = 0
for e in g:
sum += e
print(sum)
运行结果:
55
#用生成器产生斐波拉西数列
def fib(M):
n,a,b = 0,0,1
while(n<M):
yield b
a,b = b,a+b#这个是同时完成a=b,b=a+b
n += 1
for x in fib(8):
print(x,end=" ")
运行结果如下:
1 1 2 3 5 8 13 21
三、标准库的迭代工具
1.zip函数,该函数的输入参数是数目可变的任意多个可迭代对象,返回一个数据元素(tuple迭代器),每个tuple是由多个输入迭代器中对应的元素构成的
2.如果没有输入参数,则返回一个空的迭代器
3.如果输入一个可迭代对象,则返回一个数据元素(tuple的迭代器),每个tuple只有一个值
4.如果输入多个可迭代对象,则返回一个数据元素(tuple的迭代器),每个tuple由分别来自输入的可迭代对象的对象元素构成
5.zip对象是一个可迭代对象,因此可以用它构造一个list对象,但是不能用它构造一个tuple对象
result = zip()
print(list(result))
alist = [1,2,3]
result = zip(alist)
for e in result:
print(e,end=" ")
print()
str = ("许嵩","周杰伦","薛之谦")
result = zip(alist,str)
for e in result:
print(e)
运行结果如下:
[]
(1,) (2,) (3,)
(1, '许嵩')
(2, '周杰伦')
(3, '薛之谦')
a = [1,2,3]
b = ['a','b','c']
c = zip(a,b)#用zip将a,b打包
c = list(c)#要有这句话,否则报错
for i in c:
print(i)
d,e = zip(*c)#用zip将a,b解包
print(d,e)
运行结果如下:
(1, 'a')
(2, 'b')
(3, 'c')
(1, 2, 3) ('a', 'b', 'c')
6.函数enumerate,输入一个可迭代对象,返回一个enumerate对象,该对象也是一个可迭代对象,其每个元素形如(index,value)
7.函数chain()返回将多个可迭代对象串联起来的可迭代对象
import itertools#需要先导入这个模块
it1 = [1,2,3]
it2 = (2,3,4)
it = itertools.chain(it1,it2)
for e in it:
print(e)
运行结果如下:
'''
1
2
3
2
3
4
'''
8.函数count() 该函数返回一个迭代器,迭代器产生一个均匀的数字序列,该序列的开始值是start,两个相邻的差是step,这个序列是一个无限序列
from itertools import count
for i in count(10):#start=10 默认step=1
if i > 20:
break
print(i)
'''
10
11
12
13
14
15
16
17
18
19
20
'''
9.函数islice()也是itertools的一个函数,函数格式如下:
islice(iterable,stop)
islice(iterable,start,stop[,step])
该函数用于从可迭代对象中产生一个切片对象,其中,stop是切片的结束位置,start是开始位置,而step是步长
from itertools import islice,count
#2即是步长
#count(10)是一个迭代器
for i in islice(count(10),5,10,2):#第五个开始,到第十个,step=2
print(i)
运行结果如下:
'''
15
17
19
'''
10.函数cycle()作用于一个可迭代对象,产生一个重复循环的iterable对象中值的迭代器
from itertools import cycle
count = 0
for item in cycle('xyz'):
if count > 9:
break
print(item,end=" ")
count += 1
'''
x y z x y z x y z x
'''
11.#函数repeat该函数用于产生一个times个重复值为object的迭代器,它和函数cycle()的区别是,它只作用于一个有值的对象object,而函数cycle()作用于一个有多个值的可迭代对象
from itertools import repeat
r = repeat(7,3)#重复一个对象 多少次
for i in r:
print(i)
'''
7
7
7
'''