Python 可迭代对象,迭代器,生成器

可迭代对象(iterable)

简介
  • 凡是可作用于for...in...循环的对象都是 Iterable 类型:

    • 一类是集合数据类型,如 list 、 tuple 、 dict 、 set 、 str 等;

    • 一类是 generator ,包括生成器和带 yield 的generator function。 这些可以直接作用于 for 循环的对象统称为可迭代对象: Iterable

  • 可以使用 isinstance() 判断一个对象是否是 Iterable 对象

from collections import Iterable

simple_list = [1, 2, 3, 4, 5]
simple_dict = {'name': 'Tom', 'age': 20}

print(isinstance(simple_list, Iterable))  # True
print(isinstance(simple_dict, Iterable))  # True

迭代器(iterator)

简介
  • 可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
  • 生成器都是 Iterator 对象,集合数据类型如 list 、 dict 、 str 等是 Iterable 但不是 Iterator ,不过可以通过 iter() 函数获得一个 Iterator 对象
  • 迭代器对象可以使用常规for语句进行遍历
  • 迭代器对象一定是可迭代对象,Iterator继承于Iterable
  • 优点:
    • 省内存:迭代器不需要事先准备好整个迭代过程中的所有元素,仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或销毁。这也是迭代器的一大优点:适合用于遍历一个巨大的或无限的集合。
from collections import Iterator

simple_list = [1, 2, 3, 4, 5]
simple_dict = {'name': 'Tom', 'age': 20}

print(isinstance(simple_list, Iterator))  # False
print(isinstance(simple_dict, Iterator))  # False

my_iter = iter(simple_list)
print(isinstance(my_iter, Iterator))  # True
遍历迭代器
  1. 方式一:for…in…
simple_list = [1, 2, 3, 4, 5]
it = iter(simple_list)
for i in it:
    print(i)
  1. 方式二:next(),返回迭代器的下一个项目
import sys

simple_list = [1, 2, 3, 4, 5]
it = iter(simple_list)
while True:
    try:
        print(next(it))
    except:
        sys.exit()
自定义迭代器
  • __iter__()方法:返回迭代器对象本身;
  • __next__()方法:返回容器中的下一个元素,在结尾时引发StopIteration异常终止迭代器。
from collections import Iterator


class MyIterator:
    def __init__(self, max):
        self.max = max
        self.id = 0

    def __next__(self):
        if self.id < self.max:
            self.id += 1
            return self.id
        else:
            raise StopIteration('没有元素')

    def __iter__(self):
        return self


my_iterator = MyIterator(5)

print('是否是迭代器:', isinstance(my_iterator, Iterator))

for item in my_iterator:
    print(item)

输出信息:

是否是迭代器: True
1
2
3
4
5
自定义可迭代对象
from collections import Iterator
from collections import Iterable


# 迭代器对象
class MyIterator:
    def __init__(self, arrs):
        self.index = 0
        self.arrs = arrs

    def __next__(self):
        if self.index > len(self.arrs) - 1:
            raise StopIteration
        else:
            self.index += 1
            return self.arrs[self.index - 1]

    def __iter__(self):
        return self


# 可迭代对象
class MyIterable:
    def __init__(self, arrs):
        self.arrs = arrs

    def __iter__(self):
        return MyIterator(self.arrs)


my_iterable = MyIterable([1, 2, 3, 4, 5, 6])

print('是否是可迭代对象', isinstance(my_iterable, Iterator))
print('是否是迭代器', isinstance(my_iterable, Iterable))

for item in my_iterable:
    print(item)

输出信息:

是否是可迭代对象 False
是否是迭代器 True
1
2
3
4
5
6

可迭代对象和迭代器总结

  • 可以用for循环遍历的对象统称为可迭代对象(Iterable),其内部实现__iter__()方法
  • 可以被next()函数调用,不断返回下一个值的对象被成为迭代器(Iterator),其内部实现__iter__()__next__()方法
  • 迭代器继承于可迭代对象
from collections import Iterable, Iterator


class MyIterable:
    def __iter__(self):
        pass


class MyIterator:
    def __iter__(self):
        pass

    def __next__(self):
        pass


my_iterable = MyIterable()
my_iterator = MyIterator()

print(isinstance(my_iterable, Iterable))
print(isinstance(my_iterable, Iterator))

print(isinstance(my_iterator, Iterable))
print(isinstance(my_iterator, Iterator))

输出信息:

True
False
True
True

生成器(generator)

简介

生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写__iter__()__next__()方法了,只需要一个yiled关键字。 生成器一定是迭代器。

from collections import Iterator

simple_list = [x for x in range(5)]
simple_tuple = (x for x in range(5))

print(isinstance(simple_list, Iterator))
print(isinstance(simple_tuple, Iterator))

输出信息:

False
True
生成器函数

定义一个生成器函数

def fib(n):
    a, b, count = 0, 1, 0
    while count < n:
        yield b
        a, b = b, a + b
        count += 1
遍历方式一:for…in…
f = fib(10)

for i in f:
    print(i, end=' ')

输出信息:

1 1 2 3 5 8 13 21 34 55 
遍历方式二:next()
f = fib(10)

while True:
    try:
        x = next(f)
        print(x, end=' ')
    except StopIteration as e:
        break

输出信息:

1 1 2 3 5 8 13 21 34 55 
遍历方式三:send()

send是传递值给yield表达式

def func():
    n = 0
    while True:
        y = yield n
        print(y)
        n += 1


# 使用send调用生成器
f = func()

t = f.send(None)
print(t)
x = f.send('value')
print(x)
x = f.send('value2')
print(x)

输出信息:

0
value
1
value2
2

执行顺序:先返回0 -> 再输出value -> 在返回1 -> 再输出value2 -> 再返回2

和next用法比较类似

使用send生成斐波拉契数列

def fib(n):
    a, b, count = 0, 1, 0
    while count < n:
        t = yield b
        print(t)
        a, b = b, a + b
        count += 1


# 使用send调用生成器
t = fib(5)
temp = t.__next__()
print(temp)
while True:
    try:
        x = t.send('传值')
        print('value=%s' % x)
    except StopIteration as e:
        # print('value=%s' % e.value)
        break

输出信息:

1
传值
value=1
传值
value=2
传值
value=3
传值
value=5
传值

可迭代对象,迭代器,生成器,列表之前的差异

对象 是否可迭代 是否迭代器
可迭代对象
迭代器
生成器
列表

- 容器是一系列元素的集合,str、list、set、dict、file、sockets对象都可以看作是容器,容器都可以被迭代(用在for,while等语句中),因此他们被称为可迭代对象。
- 可迭代对象实现了__iter__方法,该方法返回一个迭代器对象。
- 迭代器持有一个内部状态的字段,用于记录下次迭代返回值,它实现了__next____iter__方法,迭代器不会一次性把所有元素加载到内存,而是需要的时候才生成返回结果。
- 生成器是一种特殊的迭代器,它的返回值不是通过return而是用yield

猜你喜欢

转载自blog.csdn.net/qq_14876133/article/details/81207001