迭代器,生成器,解析式

在python中容器,可迭代对象,迭代器,生成器,解析式这几个概念容易混淆,它们的关系如下图所示

容器(container)

容器是用来储存多个数据的一种数据结构,python中的容器有

  1. list,deque,...
  2. set,frozeset,...
  3. dict,defalutdict,orderdict,counter,...
  4. tuple,namedtuple,...
  5. str

可迭代对象(Iterable )

可以直接作用于for循环的对象统称为可迭代对象,即实现了__iter__方法或__getitem__的对象,包括以下对象

  1. 大部分容器(container),如list、tuple、dict、set、str等
  2. 流式数据处理对象,如文件对象,管道对象等
  3. 生成器,包括生成器函数和生成器表达式。

迭代器(Iterator)

  1. 迭代器是实现了__next__()方法的对象。
  2. 迭代器被next()函数调用返回下一个值,直到没有数据时抛出StopIteration错误。

可迭代对象和迭代器关系

  1. Iterable可以通过iter()函数转换得到 Iterator,
  2. Iterator可以直接作用于for循环,所以Iterator是Iterable。Iterator是继承Iterable的。
  3. 可迭代对象的大小是确定的,但迭代器的迭代次数是不确定的,每调用一次next()就往下走一步,它是惰性的。

实例

isinstance() 是python内建函数,返回对象是否是类或其子类的实例。
print(isinstance([], collections.Iterable))  # True
print(isinstance([], collections.Iterator))  # False
print(isinstance(iter([]), collections.Iterator))  # True
print(isinstance(iter([]), collections.Iterable))  # True
# 生成器是一种特殊的迭代器,Generator类继承了Iterator
print(isinstance((x * x for x in range(10)), collections.Iterable))  # True
# 创建可迭代对象的三种方式
class FibIterator():
    def __init__(self, f):
        self.f = f
    def __iter__(self):
        return self
    def __next__(self):
        if self.f.num > 10:
            raise StopIteration()
        self.f.num += 1
        self.f.a, self.f.b = self.f.b, self.f.a + self.f.b
        return self.f.a
class FibIterable():
    def __init__(self):
        self.a = 0
        self.b = 1
        self.num = 0
    def __iter__(self):
        return FibIterator(self)
class FibIterable2():
    def __init__(self):
        self.a = 0
        self.b = 1
        self.num = 0
    def __iter__(self):
        while self.num <= 10:
            self.num += 1
            self.a, self.b = self.b, self.a + self.b
            yield self.a
class FibIterable3():
    def __init__(self):
        self.a = 0
        self.b = 1
        self.num = 0
    def __getitem__(self, item):
        if item > 10:
            raise StopIteration()
        self.a, self.b = self.b, self.a + self.b
        return self.a
f = FibIterable()
for i in f:
    print(i, end=' ')
print()  # 1 1 2 3 5 8 13 21 34 55 89 
f2 = FibIterable2()
for i in f2:
    print(i, end=' ')
print()  # 1 1 2 3 5 8 13 21 34 55 89 
f3 = FibIterable3()
for i in f3:
    print(i, end=' ')
print()  # 1 1 2 3 5 8 13 21 34 55 89

生成器(generator )

  1. 生成器其实就是一种特殊的迭代器。它是一种更为高级、更为优雅的迭代器。
  2. 生成器有两种类型:生成器函数以及生成器表达式。生成器函数就是包含yield参数的函数。生成器表达式与列表解析式类似。
  3. 形如 (elem for elem in [1, 2, 3]) 的表达式,称为生成器表达式。所以只要把列表解析式的[]改成()就变成了生成器
  4. 生成器使用了惰性计算,即在使用的时候才产生结果。所以在数据较多的情况下减少内存占用
  5. Gennerator类继承了Iterator。

生成器的两种使用形式实例

gen = (i for i in range(2))
print(gen)  # <generator object <genexpr> at 0x000000000216FDB0>
def f(n):
    for i in range(n):
        yield i
print(f(2))  # <generator object f at 0x000000000216FEB8>
for i in gen:
    print(i, end='')  # 01
for i in f(2):
    print(i, end='')  # 01
利用生成器实现斐波那契数列
def fib(n):
    a = 0
    b = 1
    for i in range(n):
        a, b = b, a + b
        yield a
for i in fib(10):
    print(i, end=' ')

输出

1 1 2 3 5 8 13 21 34 55 

解析式

  1. 解析式包括列表解析式,集合解析式,字典解析式
  2. 解析式能用一行代码代替十几行代码,而且不损失任何可读性。而且,效率还要高很多

列表解析基本语法

[expression for iter_val in iterable]

[expression for iter_val in iterable if cond_expr]

集合解析基本语法

{expression for iter_val in iterable]}

字典解析基本语法

{expression1: expression2 for iter_val in iterable}

实例

print([i ** 2 for i in range(1, 11)])  # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
print([i ** 2 for i in range(1, 11) if i < 5])  # [1, 4, 9, 16]
print([(a, b) for a in range(1, 3) for b in ['x', 'y']])  # [(1, 'x'), (1, 'y'), (2, 'x'), (2, 'y')]
print('\n'.join([' '.join(['%d*%d=%d' % (x, i, x * i) for i in range(1, x + 1)]) for x in range(1, 10)]))
# 1*1=1
# 2*1=2 2*2=4
# 3*1=3 3*2=6 3*3=9
# 4*1=4 4*2=8 4*3=12 4*4=16
# 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
# 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
# 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
# 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
# 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
print({x * x for x in range(1, 11)})  # {64, 1, 4, 36, 100, 9, 16, 49, 81, 25}
print({x: x * x for x in range(1, 11)})  # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100}

猜你喜欢

转载自blog.csdn.net/xingjingb/article/details/81286313