Python学习笔记(10)-生成器generator和迭代器Iterator

生成器generator

在创建列表的时候,存储的内容和大小已经固定,若创建的列表包含大量的元素,则会占据很大的存储空间,而且若只需要访问列表的前几个元素,则会造成较大的资源浪费。而使用生成器generator即可避免这样的问题,generator是根据已经写好的逻辑,动态循环创建的。

1.第一种创建方法,把列表解析的符号[]换成(),如下

代码:

a = [n for n in range(5)]  # 返回的是list,可直接输出存储的数据
b = (n for n in range(5))  # 返回的是个generator,不能直接输出数据
print(a)
print(b)

结果:

[0, 1, 2, 3, 4]
<generator object <genexpr> at 0x0000000001131360>

1.1 获取generator存储的数据,可以用next()方法,例如

代码:

b = (n for n in range(5))
print(next(b))  # 输出3次
print(next(b))
print(next(b))

结果:

0
1
2

(注意:若next()输出的次数大于生成器存储的元素个数,则会抛出StopIteration错误)

1.2 查看generator存储的数据,每次都调用next()太过于繁琐,建议用for...in...循环,例如

代码:

b = (n for n in range(5))
for value in b:
    print(value) 

结果:

0
1
2
3
4

for循环调用,可以不用担心抛出StopIteration错误

2.第二种创建方法,在函数定义中使用yield关键字,则该函数即为生成器函数,如下

代码:

def Fibonacci(number):
    n, a, b = 0, 0, 1
    while n < number:
        yield b   # 使用yield关键字,将b存储到generator中
        a, b = b, a + b  # a = b , b = a + b 
        n += 1
    return 'over'  # 在生成器函数中的return,不返回信息,而是将值存储在抛出的StopIteration中,可通过捕获异常来获取


print([n for n in Fibonacci(8)])  # 使用列表解析,将结果存储到数组中,为了看着好看而已→_→

结果:

[1, 1, 2, 3, 5, 8, 13, 21]

普通函数和生成器函数的区别:

普通函数中遇到return语句或者执行到函数末尾会自动返回,而在生成器函数中,return是不返回的,而是在调用next()函数之后开始执行,而在yield处返回,下次在调用next()则再上次停止的yield处继续开始执行

2.1 通过try-except语句来获取return的返回值,如下

代码:

result = Fibonacci(8)
while True:
     try:
         x = next(result)  #  其实for循环就是一次次的执行next()函数
     except StopIteration as e:
         print('返回值是:', e.value)
         break

结果:

返回值是: over

e.g.

利用生成器函数,将杨辉三角的每一行数据存储到list中输出。

代码:

def YHtriangle(max):  # 构造杨辉三角的逻辑  max>2时,每个数都等于上一行同一位置的数+这个位置前一位置的数
    n, L = 0, [1]
    while n < max:
        yield L  # 此处将L列表存储到生成器中
        L.append(0) # 存储后,在列表末尾添加0,为了下一行计算数据
        L = [L[i - 1] + L[i] for i in range(len(L))]  # 注意是range(len(L)),i-1=-1,每次取值都是上一句添加的0,
        n += 1

def getYHtriangle(num):  # 输出数据
    for n in YHtriangle(num):
        print(n)

getYHtriangle(4)  # 调用函数

结果:

[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]

迭代器Iterator和可迭代对象Iterable

笔记(3)中记过,可使用collections模块的Iterable类型来判断是否可被for循环,补充,生成器generator或者是生成器函数也是可迭代对象Iterable

可以被next()函数调用,并且不断返回下一个值的对象,叫做迭代器Iterator

同样可以使用isinstance()函数来判断是否是迭代器(需要先导入Iterable)

代码:

from collections import Iterator

print(isinstance(123, Iterator))    # 不是可迭代对象Iterable,也不是迭代器Iterator
print(isinstance('abc', Iterator))  # 字符串,列表,字典虽然可迭代Iterable,但不是迭代器Iterator
print(isinstance(['a', 'b'], Iterator))
print(isinstance(('a', 3), Iterator))
print(isinstance((n for n in range(5)), Iterator))  # 只有生成器是一个迭代器

结果:

False
False
False
False
True

字符串,列表,字典虽然只是可迭代,不是迭代器,但是可以通过函数iter()获取一个迭代器Iterator,例如。

代码:

from collections import Iterator

L = [1, 2, 3, 4]
print(isinstance(L, Iterator))
print(isinstance(iter(L), Iterator))

结果:

False
True
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值