Python基础入门笔记:迭代器和生成器

2018-09-2010:12:43后端程序开发Comments1,766 views字数 2908阅读模式

迭代器和生成器

1.1 Python迭代器

迭代器是一个可以记住遍历的位置的对象。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

迭代器只能往前不会后退。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

迭代器有两个基本的方法:iter()next(),且字符串、列表或元组对象都可用于创建迭代器,迭代器对象可以使用常规 for 语句进行遍历,也可以使用 next() 函数来遍历。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

具体的实例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

# 1、字符创创建迭代器对象
str1 = 'jaybo'
iter1 = iter ( str1 )

# 2、list对象创建迭代器
list1 = [1,2,3,4]
iter2 = iter ( list1 )

# 3、tuple(元祖) 对象创建迭代器
tuple1 = ( 1,2,3,4 )
iter3 = iter ( tuple1 )

# for 循环遍历迭代器对象
for x in iter1 :
    print ( x , end = ' ' )

print('\n------------------------')

# next() 函数遍历迭代器
while True :
    try :
        print ( next ( iter3 ) )
    except StopIteration :
        break
复制代码

最后输出的结果:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

j a y b o
------------------------
1
2
3
4
复制代码

list(列表)生成式:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

语法为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

[expr for iter_var in iterable] 
[expr for iter_var in iterable if cond_expr]
复制代码

第一种语法:首先迭代 iterable 里所有内容,每一次迭代,都把 iterable 里相应内容放到iter_var 中,再在表达式中应用该 iter_var 的内容,最后用表达式的计算值生成一个列表。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

第二种语法:加入了判断语句,只有满足条件的内容才把 iterable 里相应内容放到 iter_var 中,再在表达式中应用该 iter_var 的内容,最后用表达式的计算值生成一个列表。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

实例,用一句代码打印九九乘法表:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

print('\n'.join([' '.join ('%dx%d=%2d' % (x,y,x*y)  for x in range(1,y+1)) for y in range(1,10)]))
复制代码

输出结果:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

1x1= 1
1x2= 2 2x2= 4
1x3= 3 2x3= 6 3x3= 9
1x4= 4 2x4= 8 3x4=12 4x4=16
1x5= 5 2x5=10 3x5=15 4x5=20 5x5=25
1x6= 6 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36
1x7= 7 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49
1x8= 8 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64
1x9= 9 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81
复制代码

1.2 生成器

在 Python 中,使用了 yield 的函数被称为生成器(generator)。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值。并在下一次执行 next() 方法时从当前位置继续运行。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

①创建:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

生成器的创建:最简单最简单的方法就是把一个列表生成式的 [] 改成 ()文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

gen= (x * x for x in range(10))
print(gen)
复制代码

输出结果:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

generator object  at 0x0000000002734A40
复制代码

创建 List 和 generator 的区别仅在于最外层的 [] 和 () 。但是生成器并不真正创建数字列表, 而是返回一个生成器,这个生成器在每次计算出一个条目后,把这个条目“产生” ( yield ) 出来。 生成器表达式使用了“惰性计算” ( lazy evaluation,也有翻译为“延迟求值”,我以为这种按需调用 call by need 的方式翻译为惰性更好一些),只有在检索时才被赋值( evaluated ),所以在列表比较长的情况下使用内存上更有效。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

②以函数形式实现生成器:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

其实生成器也是一种迭代器,但是你只能对其迭代一次。这是因为它们并没有把所有的值存在内存中,而是在运行时生成值。你通过遍历来使用它们,要么用一个“for”循环,要么将它们传递给任意可以进行迭代的函数和结构。而且实际运用中,大多数的生成器都是通过函数来实现的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

生成器和函数的不同:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

函数是顺序执行,遇到 return 语句或者最后一行函数语句就返回。而变成 generator 的函数,在每次调用 next() 的时候执行,遇到 yield语句返回,再次执行时从上次返回的 yield 语句处继续执行。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

举个例子:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

def odd():
    print ( 'step 1' )
    yield ( 1 )
    print ( 'step 2' )
    yield ( 3 )
    print ( 'step 3' )
    yield ( 5 )

o = odd()
print( next( o ) ) 
print( next( o ) ) 
print( next( o ) )
复制代码

输出结果:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

step 1
1
step 2
3
step 3
5
复制代码

可以看到,odd 不是普通函数,而是 generator,在执行过程中,遇到 yield 就中断,下次又继续执行。执行 3 次 yield 后,已经没有 yield 可以执行了,如果你继续打印 print( next( o ) ) ,就会报错的。所以通常在 generator 函数中都要对错误进行捕获。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

打印杨辉三角:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

def triangles( n ):         # 杨辉三角形
    L = [1]
    while True:
        yield L
        L.append(0)
        L = [ L [ i -1 ] + L [ i ] for i in range (len(L))]

n= 0
for t in triangles( 10 ):   # 直接修改函数名即可运行
    print(t)
    n = n + 1
    if n == 10:
        break
复制代码

输出结果:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
复制代码

1.3 延伸

①反向迭代文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

使用 Python 中有内置的函数 reversed()文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

要注意一点就是:反向迭代仅仅当对象的大小可预先确定或者对象实现了 __reversed__() 的特殊方法时才能生效。 如果两者都不符合,那你必须先将对象转换为一个列表才行。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

②同时迭代多个序列文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

为了同时迭代多个序列,使用 zip() 函数,具体示例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

names = ['jaychou', 'zjl', '周杰伦']
ages = [18, 19, 20]
for name, age in zip(names, ages):
     print(name,age)
复制代码

输出的结果:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

jaychou 18
zjl 19
周杰伦 20
复制代码

其实 zip(a, b) 会生成一个可返回元组 (x, y) 的迭代器,其中 x 来自 a,y 来自 b。 一旦其中某个序列到底结尾,迭代宣告结束。 因此迭代长度跟参数中最短序列长度一致。注意理解这句话,也就是说如果 a , b 的长度不一致的话,以最短的为标准,遍历完后就结束。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html

文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/5155.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/bc/5155.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定