零基础入门python3.7 ——基础知识总结(十五) python的特性归纳

一。 生成器

我们可以通过生成列表来创建,但是由于内存是有限的与之对应的列表容器也是有限的。 假如要创建100万个元素的列表。 实际上只需要前几个元素。 那么多余的元素就会浪费大量的空间。 所以可以根据一定的规则可以在循环过程中推选出后续的元素。是、这种一边循环一遍计算的机制称之为生成器(generator)

  • 示例一

把一个列表生成器[]改成(), 从而创建一个generator

a = [x * 2 for x in range(10)]
print(a)

b = (x * 2 for x in range(10))
print(b)

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
 at 0x10b1fd650>

示例的区别在于a最外层是[]. 而b最外层是(),而且在输出结果上也有明显的差别。我们知道列表中的元素可以一一打印出来。 而generator则需要借助next()函数才能打印出结果。

b = (x * 2 for x in range(10))
print(b)

print(next(b))
print(next(b))
print(next(b))
print(next(b))
print(next(b))
print(next(b))
print(next(b))
print(next(b))
print(next(b))
print(next(b))
print(next(b))

0
2
4
6
8
10
12
14
16
18
Traceback (most recent call last):
  File "/Users/apple/Documents/重要文件/python3/python21.py", line 14, in 
    print(next(b))
StopIteration

因为generator保存的是算法。所以每次调用next()时都会计算出下一个元素。直至计算完最后一个元素在无可计算的元素时回抛出异常。当然访问generator的正确方法是通过循环。通过一次次手写调用next()访问显然不是明智之举。

b = (x * 2 for x in range(10))
print(b)

for i in b:
    print(i)

 at 0x10e5ec550>
0
2
4
6
8
10
12
14
16
18

这种访问访问方式即使访问到最后一个元素也不会抛出异常。 如果算法比较复杂。 无法用for生成还可以用函数生成。

def fib(max):
    n, a, b = 0, 1, 2
    while n < max:
        print(b)
        a, b = b, a + b
        n += 1

fib(10)


2
3
5
8
13
21
34
55
89
144

上面的函数生成一个斐波拉契数列。 这里只是一个算法但是把他稍微改造一下就成了generator。

def fib(max):
    n, a, b = 0, 1, 2
    while n < max:
        yield b
        a, b = b, a + b
        n += 1

a = fib(10)
print(a)


经过改造一个普通函数已经变成了generator。 也就意味着一个函数中只要出现了yield这个关键字他就不是普通的函数了。而是一个generator,还有一点必须要注意的是generator和普通的函数在执行流程上是有所区别的 ,普通的函数是顺序执行的。 遇到return回返回。 而generator在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。要访问上述示例中的元素最简单的还是使用循环。

def fib(max):
    n, a, b = 0, 1, 2
    while n < max:
        yield b
        a, b = b, a + b
        n += 1

a = fib(10)
print(a)

for i in a:
    print(i)


2
3
5
8
13
21
34
55
89
144

二。迭代器

通过for能遍历的一般有两种类型的数据 :一类是集合数据类型,如listtupledictsetstr等;另一类是generator,包括生成器和带yield的generator function。这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

 

  • 使用isinstance()判断一个对象是否是Iterable对象:
from collections.abc import Iterable

a = isinstance([1, 2], Iterable)
print(a)

b = isinstance(12, Iterable)
print(b)

True
False

而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

可以使用isinstance()判断一个对象是否是Iterator对象:

from collections.abc import Iterator
a = 'python'
print(isinstance(a, Iterator))

b = (x for x in range(10))
print(isinstance(b, Iterator))

False
True

生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator。可以使用iter()()函数将Iterable变成的Iterator,

from collections.abc import Iterator
a = 'python'
print(isinstance(iter(a), Iterator))

True

 

你可能感兴趣的:(python)