第3章 生成器

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 何时编写生成器
  1. 分块访问数据
    • 迭代器将一次迭代一块数据
  2. 分块计算数据
    • 在需要时它时计算数据,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)
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

壹如年少遲夏歸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值