迭代器 生成器
01 迭代器
python中有些对象是可迭代的,我们可以自己创建迭代器使自定义的类可迭代,从而可以使用for循环输出
-
for循环实现过程
- 判断xxx是否可迭代
- 调用iter函数得到xxx对象的iter方法的返回值
- iter方法的返回值是一个迭代器
- 迭代器中有iter,next就可以使用for循环
- 每次for循环返回next的返回值
- 代码示例
class Classmate():
def __init__(self):
self.names=list()
def add(self,name):
self.names.append(name)
# 如果想要对象可以迭代,必须使用__iter__方法
def __iter__(self):
return Classiterator(self) # 将自身的引用传给迭代器
# 迭代器中有__iter__,__next__就可以使用for循环
class Classiterator():
def __init__(self,class_obj):
self.iterator_obj=class_obj # 接受类的引用,从而可以使用类中的值
self.current_num=0 # 记录取值的位置
def __iter__(self): # 使迭代器成为可迭代的
pass
def __next__(self): # 每次for循环时返回next中的返回值
if self.current_num<len(self.iterator_obj.names):
ret = self.iterator_obj.names[self.current_num]
self.current_num+=1
return ret
else:
raise StopIteration
classmate=Classmate()
classmate.add('alex')
classmate.add('brown')
classmate.add('chris')
for name in classmate:
print(name)
- 代码中创建了两个类,classmate和它对应的迭代器
- 要想使一个类可迭代,就要将其自身的引用传给迭代器
- 迭代器通过_init_接收传递的参数
- 迭代器中也需要有_iter_使得迭代器可迭代
- 使用for循环输出可迭代对象时,每次返回_next_中的返回值
3.斐波那契数列迭代器
将类与迭代器整合在了一起
class Fibonacci():
def __init__(self,n):
self.n=n
self.current_num=0
self.a=1
self.b=1
def __iter__(self):
return self
def __next__(self):
if self.current_num < self.n:
result = self.a
self.a,self.b=self.b,self.a+self.b
self.current_num+=1
return result
else:
raise StopIteration
fibo=Fibonacci(10)
for num in fibo:
print(num)
02 生成器
生成器是一种特殊的迭代器,使用起来更加简单
- 简单生成列表与表达式的方法
list1=[x for x in range(10)] # 生成一个列表
gen1=(x for x in range(10)) # 生成一个生成器
print(list1)
print(next(gen1))
-
生成器函数
只要函数中有yield,它就是一个生成器使用生成器输出斐波那契数列
def create_fibo(n):
i=0
a, b=1, 1
while i<n:
ret = yield a # 只要有yield就是一个生成器的模板,调用函数时就是创建生成器
print(ret)
a, b=b, a+b
i+=1
return 'ok...'
nums=create_fibo(10) # 可以创建多个生成器,互不影响
-
启动生成器的方法
- 使用迭代的方法
for num in nums: print(num)
- 使用next
while True: try: result=next(nums) print(result) except Exception as result: print(result.value) break
- 使用send
ret=nums.send(None) print(ret) print('==============') ret=nums.send('hahaha') print(ret) print(ret) ret=nums.send('hahaha') ''' 1 ============== hahaha 1 1 hahaha '''
- send可以传递参数,默认为None
- 参数是yield的返回值,如调用ret = yield a时就返回了send传递的参数值
- 第一次调用send时,参数必须为None,或者使用next启动