032 生成器
'''next'''
def fib():
yield 1
yield 1
yield 2
# f = fib()
# print(next(f))
# print(next(f))
# print(next(f))
# for i in fib():
# print(i)
def fib():
numbers = []
while True:
if len(numbers) < 2:
numbers.append(1)
else:
numbers.append(sum(numbers))
numbers.pop(0)
yield numbers[-1]
# continue 不需要加 会自动继续上一个操作
gen = fib()
# print(next(gen))
# print(next(gen))
# print(next(gen))
# print(next(gen))
# print(next(gen))
'''StopIterarion 异常'''
def my_func(foo, add_extra_thing=True):
foo += '\n add things'
if not add_extra_thing:
return foo
foo += "\n added extra things"
return foo
# 截断
def generator():
yield 1
yield 2
# return
raise StopIteration
yield 3
gen = generator()
print(next(gen))
print(next(gen))
print(next(gen))
033 生成器之间的交互
'''
生成器的协议提供了一个额外的send方法,该方法允许生成器反向沟通
'''
# 普通生成器
def squares():
cursor = 1
while True:
yield cursor ** 2
cursor += 1
s = squares()
print(next(s))
for i in range(10):
print(next(s))
def squares(cursor):
while True:
response = yield cursor ** 2 # yield 的返回值是由 对象.send 方法传进来的
# print(response)
if response:
cursor = int(response)
else:
cursor += 1
s = squares(1)
print(next(s))
print(next(s))
print(s.send(5)) #
print(next(s))
print(next(s))
# 返回send() 之前的对象;继续生成
def squares():
cursor = 1
response = None
while True:
if response:
response = yield int(response) ** 2
else:
response = yield cursor ** 2
cursor += 1
s = squares()
print(next(s))
print(s.send(5))
print(next(s))
print(next(s))
034 迭代器与迭代对象
-
''' 1)可迭代对象包含迭代器。 2)如果一个对象拥有__iter__方法,其是可迭代对象;如果一个对象拥有next方法,其是迭代器。 3)定义可迭代对象,必须实现__iter__方法;定义迭代器,必须实现__iter__和next方法。 range 对象并不是一个生成器 理解:生成器可以是迭代器,并不一定是迭代对象;并非所有的迭代对象都是迭代器 ''' r = range(5) # print(next(r)) # TypeError: 'range' object is not an iterator # iter 方法返回的实际迭代器是一个生成器,并响应next 方法 iterator = iter(r)
print(next(iterator))
#### 035 标准库中的生成器
- `range()`
- `dict.items() keys() values()`
- items 迭代器仅重引用的字典中读取数据的生成器,如果字典发生变化,抛出异常`RuntimeError`
- `zip()`
```python
z = zip(['a', 'b', 'c', 'd'], ['x', 'y', 'z'])
print(next(z))
print(next(z))
print(next(z))
print(next(z)) # StopIteration
-
map()
-
文件对象
036 何时编写生成器
- 分块访问数据
- 迭代器将一次迭代一块数据
- 分块计算数据
- 在需要时它时计算数据,
range()
斐波那契数列
- 在需要时它时计算数据,
037 何时使用生成器单例模式
-
常见情况,对象既是迭代对象又是迭代器;因为迭代对象只返回
self
, 所以在一个对象上重复调用__iter__
将返回同一个对象,这本质上意味着对象仅支持一个活动的迭代器。-
简单的生成器并不是单例模式
-
单例模式
class Fib: def __init__(self): self.num = [] def __iter__(self): return self def __next__(self): if len(self.num) < 2: self.num.append(1) else: self.num.append(sum(self.num)) self.num.pop(0) return self.num[-1] def send(self, value): pass f = Fib() il = iter(f) print(next(il), next(il), next(il)) i2 = iter(f) print(next(i2))
-
038 生成器中的生成器
-
def gen1(): yield 'foo' yield 'bar' def gen2(): yield 'spam' yield 'eggs' def gen3(): yield from gen1() yield from gen2() for i in gen3(): print(i)