Loading

Python迭代器生成器与生成式

Python迭代器生成器与生成式

什么是迭代

迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。

例如for循环

a = ['abc', 123, ['4', 45]]
for i in a:
    print(i)
#==========输出=============
abc
123
['4', 45]

for就是把这个列表迭代了一遍,但是根据迭代的定义每一次迭代得到的结果会作为下一次迭代的初始值。这也没看到用了上一次的值啊。

这里介绍两个函数__iter__()__next__,一个可迭代序列(同时它也是一个对象),它有一个__iter__()方法,可以返回一个迭代器对象,这个迭代器对象里面有一个__next__()方法,它可以将迭代器对象一个一个向下迭代。

例如上例

a = ['abc', 123, ['4', 45]]

#print(a.__iter__())
x = a.__iter__()
print(x.__next__())
print(x.__next__())
print(x.__next__())

##其实还有一种迭代形式,一个调用内置方法一个调用外部方法罢了
x = iter()
next(x)
next(x)
next(x)

x = iter(a)
print(next(x))
print(next(x))
print(next(x))

#===========输出结果=========
abc
123
['4', 45]
abc
123
['4', 45]

但是如果再加一个print(x.__next__())的话python会抛出一个异常。

然后我们可以结合while循环就可以大致猜出for迭代时的内部执行机理了。

a = ['abc', 123, ['4', 45]]

y = a.__iter__()
while True:
    try:
        print(y.__next__())
    except StopIteration:
        break
        
#===========输出================
abc
123
['4', 45]

这样就把列表a迭代完了。

什么是生成式

要创建一个列表,就要有一个中括号,里面的数据就是列表的内容。如果我要创建一个列表,列表里面有按顺序的1~100所有的整数,一个一个输入吗?

有人可能说用循环,例如

x = []
for i in range(1, 101):
    x.append(i)

确实这样是可以的,但是有了生成式可能会更加简单一点

x = [i for i in range(1, 101)]

再中括号里面,一个应该写入数据的地方放一个循环,在C语言看来这简直就是疯了。不过这也体现了python的灵活强大。

其实中括号里面除了加for循环还能加条件判断,例如

x = [i for i in range(1, 101) if i % 2 and not i % 3]
#列举出所有1~100能被3整除不能被2整除的数

除了list列表有这种操作以外,还有字典可以这样操作

字典

dict1 = {i:i + 1 for i in range(1, 101)if i % 2 and not i % 3 }

执行结果

{3: 4, 9: 10, 15: 16, 21: 22, 27: 28, 33: 34, 39: 40, 45: 46, 51: 52, 57: 58, 63: 64, 69: 70, 75: 76, 81: 82, 87: 88, 93: 94, 99: 100}

应该能看出点什么来了,也挺简单。

什么是生成器

就是有一个跟return差不多的东西yieldreturn返回之后程序就退出了,但是yield会把程序暂停,然后等你需要的时候来继续执行,但是跟return又有一点不一样,yield是迭代器的一种,返回的是一个生成器对象,需要借用next()函数来进行迭代。

其实yield就是一种特殊的迭代器。

def sc1():
    yield 'one'
    yield 'two'

def sc2():
    return 'one'


s1 = sc1()
s2 = sc2()
print(type(s1))
print(type(next(s1)))
print(type(s2))

输出

<class 'generator'>
<class 'str'>
<class 'str'>

对于生成器的使用,最简单的例如

def sc():
    print('进入函数1')
    yield 'one'
    print('进入函数2')
    yield 'two'

s = sc()
print(next(s))
print(next(s))

#============输出===========
进入函数1
one
进入函数2
two

使用与迭代器几乎一模一样

用这个生成一个斐波拉契数列可以这样写

def feb(x):
    count = 0
    a = 0
    b = 1
    while count < x:
        yield a
        a, b = b, a + b
        count += 1

这样就会生成一个斐波拉契数列前x项的可迭代序列

可以测试一下,用for循环迭代它

for i in feb(10):
    print(i,end=' ')

输出

0 1 1 2 3 5 8 13 21 34 
posted @ 2021-01-13 15:46  [X_O]  阅读(60)  评论(0编辑  收藏  举报