Python基础--迭代器&生成器

1.迭代器 Iterator

迭代器是指用 iter(iterable) 函数返回的对象(实例), 可以记住遍历的位置的对象, 间接访问可迭代对象的一种方式。

迭代器可以用 next(Iterator) 函数依次获取可迭代对象的值, 表示一个惰性计算的序列, 迭代器只能往前取值,不会后退, 也可以用 for 语句遍历;

  • iter()、next()函数
1. iter(iterable) 从可迭代对象中返回一个迭代器Iterator,iterable必须是一个可迭代对象
2. next(Iterator) 从迭代器Iterator 中获取下一个记录,如果无法获取下一条记录,则触发StopIteration,异常来通知调用者已无数据可提供
  • 可迭代对象
集合数据类型:
str、list、tuple、dict、set、frozenset

函数返回值:
range(), map(), filter(), sorted(), zip(), enumerate()

注:凡是可作用于for循环的对象都是Iterable类型, 集合数据类型如list、dict、str等是Iterable, 但不是Iterator,不过可以通过iter()函数获得一个Iterator对象

L = [1,3,5,7,9] # L为可迭代对象
L.__next__()
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-13-a270d7e520f0> in <module>
      1 L = [1,3,5,7,9] # L为可迭代对象
----> 2 L.__next__()


AttributeError: 'list' object has no attribute '__next__'
L = [1,3,5,7,9] # L为可迭代对象
next(L)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-14-1dc6ff802149> in <module>
      1 L = [1,3,5,7,9] # L为可迭代对象
----> 2 next(L)


TypeError: 'list' object is not an iterator
L = [1,3,5,7,9] # L为可迭代对象
it = iter(L)    # 变量it 绑定迭代器
v = next(it)    # v 绑定
print(v)
print(it.__next__())
print(next(it))
print(next(it))
print(next(it))
print(next(it))
1
3
5
7
9



---------------------------------------------------------------------------

StopIteration                             Traceback (most recent call last)

<ipython-input-15-658214e2d174> in <module>
      7 print(next(it))
      8 print(next(it))
----> 9 print(next(it))


StopIteration: 
  • for循环本质上就是通过不断调用next()函数实现的
for x in [1, 2, 3, 4, 5]:
    print(x)
    
# 完全等价于:
it = iter([1, 2, 3, 4, 5])
while True:
    try:
        # 获得下一个值:
        print(next(it))
    except StopIteration:
        # 遇到StopIteration就退出循环
        break
1
2
3
4
5
1
2
3
4
5

2. 生成器:Generator(python2.5 之后)

生成器是指能够动态提供数据的对象,只用在调用的时候才会生成相应的数据,只记录当前数据,生成器对象也是迭代器对象,当迭代超出范围后,产生一个StopIteration

  • 生成器有两种
只能用for 语句、next 函数、生成器属性取值,取值时生成器才会生成要用到的数据
1、生成器函数

2、生成器表达式

注:生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。

1. 生成器函数:

含有yield 语句的函数是生成器函数,此函数调用将返回一个生成器对象 yield 翻译为生成、产生

  • yield语句格式:
yield 表达式
  • 说明:
yield 用于def 函数中,目的是将此函数作为生成器函数使用
yield 用来生成数据,此数据提供给迭代器的next(generator) 函数使用
yield 记住当前执行环境暂停函数,并返回数据给调用处,再次取数据时执行回到yield 语句处向下执行

练习:写一个生成器函数,用于生成n 个斐波那契数,n 以参数的形式传入

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        # print(b)
        yield b
        a, b = b, a + b
        n = n + 1
    # return "done"

g = fib(6)
while True:
    try:
        x = next(g)
        print("g", x)
    except Exception as e:
        print("Generator return value:", e.value)
        break
g 1
g 1
g 2
g 3
g 5
g 8
Generator return value: None
  • 生成器函数说明:
生成器函数的调用将返回一个可迭代对象
生成器函数调用return 语句,当迭代超出范围后,产生一个StopIteration 异常后加return 的值(如:StopIteration: done)
生成器函数每次用next() 函数取值时才会执行,遇到yield语句后将停止执行,并返回数据

2. 生成器表达式:generator expression

语法:(表达式 for 变量 in 可迭代对象 [if 真值表达式]) 注:[]内的if部分可以省略,形式很像列表生成式,只是把中括号改成了小括号

作用:用推导式的形式生成一个新的生成器,可以用生成器的属性 .__next__() 取值
a = (x*2 for x in range(5))  # 使用生成器表达式来创建一个生成器
a
<generator object <genexpr> at 0x10a897228>
print(next(a), a.__next__())
0 2
s = iter(a)
s
<generator object <genexpr> at 0x10a897228>
print(s.__next__(), next(s))
4 6
a.__next__()
a.__next__()
---------------------------------------------------------------------------

StopIteration                             Traceback (most recent call last)

<ipython-input-11-5e73900f2c53> in <module>
      1 a.__next__()
----> 2 a.__next__()


StopIteration: 
  • 生成器表达式和列表推导式的区别:
1、生成器表达式中产生的数据是现用现生成,不记住之前生成的数据,也不能使用已经生成过的数据,当迭代超出范围后,产生一个StopIteration
2、列表推导式会一次性生成所有数据
  • 生成器的并发
import time

def consumer(name):
    print("%s 准备吃包子!" % name)
    while True:
        baozi = yield
        print("包子[%s] 来了,被[%s] 吃了!" % (baozi, name))

def producer(name):
    c = consumer("A")
    c2 = consumer("B")
    y = c.__next__()
    y1 = c2.__next__()
    print("准备做包子!", y, y1)
    for i in range(10):
        time.sleep(1)
        print("做了2 个包子")
        c.send(i)
        c2.send(i)

producer("庄")
A 准备吃包子!
B 准备吃包子!
准备做包子! None None
做了2 个包子
包子[0] 来了,被[A] 吃了!
包子[0] 来了,被[B] 吃了!
做了2 个包子
包子[1] 来了,被[A] 吃了!
包子[1] 来了,被[B] 吃了!
做了2 个包子
包子[2] 来了,被[A] 吃了!
包子[2] 来了,被[B] 吃了!
做了2 个包子
包子[3] 来了,被[A] 吃了!
包子[3] 来了,被[B] 吃了!
做了2 个包子
包子[4] 来了,被[A] 吃了!
包子[4] 来了,被[B] 吃了!
做了2 个包子
包子[5] 来了,被[A] 吃了!
包子[5] 来了,被[B] 吃了!
做了2 个包子
包子[6] 来了,被[A] 吃了!
包子[6] 来了,被[B] 吃了!
做了2 个包子
包子[7] 来了,被[A] 吃了!
包子[7] 来了,被[B] 吃了!
做了2 个包子
包子[8] 来了,被[A] 吃了!
包子[8] 来了,被[B] 吃了!
做了2 个包子
包子[9] 来了,被[A] 吃了!
包子[9] 来了,被[B] 吃了!

3. 迭代工具函数

迭代工具函数的作用是生成一个个性化的可迭代对象

  • zip(iter[, iter,…]) 返回一个zip对象,此对象用于生成元组,此元组的个数由最小的可迭代对象决定
numbers = [10086, 10000, 10010, 95588]
names = ['中国移动', '中国电信', '中国联通']
for x in zip(numbers, names):
    print(x)
(10086, '中国移动')
(10000, '中国电信')
(10010, '中国联通')
  • enumerate(iterator[, start]), 生成带索引的枚举对象,返回迭代类型为索引-值对(index, value)的元组,默认索引从零开始,也可以指定start
numbers = [10086, 10000, 10010, 95588]
names = ['中国移动', '中国电信', '中国联通']
# L = [(0, '中国移动'), (1, '中国电信'), (2, '中国联通')]
for x in enumerate(names):
    print(x)

# 扩展
for no, n in enumerate(names):  # (等同于序列赋值)
    print(no, " ----->", n)
(0, '中国移动')
(1, '中国电信')
(2, '中国联通')
0  -----> 中国移动
1  -----> 中国电信
2  -----> 中国联通

练习:写一个程序,输入任意行文字,当输入空行时结束输入打印带有行号的输出结果

请输入:hello
请输入:world
请输入:bye
请输入:<回车>

输出如下:

第1行:hello
第2行:world
第3行:bye
input_words = []
while True:
    input_word = input("请输入:")
    if not input_word:
        break
    input_words.append(input_word)

for no, word in enumerate(input_words):
    print("第%s行:%s" % (no+1, word))
请输入:hello
请输入:world
请输入:bye
请输入:
第1行:hello
第2行:world
第3行:bye

练习:用生成器函数,生成素数,给出起始值为begin和终止值end,此生成器函数为

def myprimes(n, m):
    for y in range(n, m+1):
        for x in range(2, int(y**0.5)+1):
            if y % x == 0:
                break
        else:
            yield y


L = [x for x in myprimes(10, 20)]
print(L)
[11, 13, 17, 19]

练习: 写一个生成器函数,参数为n,生成斐波那契数列的前n个数

def fibonacci(n):
    L = [1, 1]
    for x in range(n - 2):
        s = 0
        s = (L[x] + L[x + 1])
        L.append(s)
    for y in L:
        yield y


L = [x for x in fibonacci(7)]
print(L)
[1, 1, 2, 3, 5, 8, 13]
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        # print(b)
        yield b
        a, b = b, a + b
        n = n + 1
    # return "done"


g = fib(6)
while True:
    try:
        x = next(g)
        print(x)
    except Exception as e:
        print("Generator return value:", e.value)
        break
1
1
2
3
5
8
Generator return value: None

同名公众号:庄AC

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值