迭代与迭代器

迭代

使用for循环遍历取值的过程叫做迭代,比如:使用for循环遍历列表获取值的过程

for value in [2, 3, 4]:
    print(value)

使用for循环遍历取值的对象叫做可迭代对象, 比如:列表、元组、字典、集合、range、字符串

如何判断对象是否是可迭代对象

from collections import Iterable

# 判断对象是否是指定类型
result = isinstance((3, 5), Iterable)
print("元组是否是可迭代对象:", result)
结果 :True

result = isinstance([3, 5], Iterable)
print("列表是否是可迭代对象:", result)
结果 :True

result = isinstance(5, Iterable)
print("整数是否是可迭代对象:", result)
结果 :False

如何自定义一个可迭代对象

在类里面定义__iter__方法创建的对象就是可迭代对象
from collections import Iterable

# 自定义可迭代对象: 在类里面定义__iter__方法创建的对象就是可迭代对象
class MyList(object):

    def __init__(self):
        self.my_list = list()

    # 添加指定元素
    def append_item(self, item):
        self.my_list.append(item)

    def __iter__(self):
        # 可迭代对象的本质:遍历可迭代对象的时候其实获取的是可迭代对象的迭代器, 然后通过迭代器获取对象中的数据
        pass

my_list = MyList()
my_list.append_item(1)
my_list.append_item(2)
result = isinstance(my_list, Iterable)

print(result)

for value in my_list:
    print(value)
执行结果:
Traceback (most recent call last):
True
  File "/Users/hbin/Desktop/untitled/aa.py", line 24, in <module>
    for value in my_list:
TypeError: iter() returned non-iterator of type 'NoneType'

##通过执行结果可以看出来,遍历可迭代对象依次获取数据需要迭代器

迭代器

如下代码会介绍到如何自定义迭代器,如何判断是否是可迭代对象
在类里面定义__iter__和__next__方法创建的对象就是迭代器对象
iter()函数与next()函数

iter函数: 获取可迭代对象的迭代器,会调用可迭代对象身上的__iter__方法
next函数: 获取迭代器中下一个值,会调用迭代器对象身上的__next__方法

from collections import Iterable, Iterator


# 自定义可迭代对象
class MyList(object):

    def __init__(self):
        # 初始化一个列表
        self.one_list = list()

    def append(self, num):
        self.one_list.append(num)

    # iter函数会调可迭代对象的iter方法
    def __iter__(self):
        my_iterator = MyIterator(self.one_list)
        print(my_iterator)
        # 返回迭代器对象
        return my_iterator


# 自定义迭代器
class MyIterator(object):

    def __init__(self, one_list):

        self.list = one_list
        # 初始化下标
        self.index = 0
        result = isinstance(self, Iterator)
        print("MyIterator创建的对象是否是迭代器:",result)

    def __iter__(self):
        return self

    def __next__(self):

        if self.index < len(self.list):
            self.index += 1
            return self.list[self.index - 1]
        else:
            # 停止迭代
            raise StopIteration


if __name__ == '__main__':

    my_list = MyList()
    my_list.append(1)
    my_list.append(2)

    myDeIterator = iter(my_list)

    # 检查是否为可迭代对象
    print(isinstance(my_list, Iterable))
    
    #for item in myDeIterator:
    #	 print(item)
    
    while True:
        try:
            # 调用迭代器的__next__方法
            print(next(myDeIterator))

        except:
            break

for的本质

遍历的是可迭代对象

for item in myDeIterator 循环的本质就是先通过iter()函数获取可迭代对象my_list的迭代器,然后对获取到的迭代器不断调用next()方法来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环结束。
遍历的是迭代器

for item in myDeIterator 循环的迭代器,不断调用next()方法来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环结束。

    #for item in myDeIterator:
    #	 print(item)
    
    #for的本质就是while 循环不断调用inter()函数和next()函数
    
    while True:
        try:
            # 调用迭代器的__next__方法
            print(next(myDeIterator))

        except:
            break

生成器

生成器是一类特殊的迭代器,它不需要再像上面的类一样写__iter__()和__next__()方法了, 使用更加方便,它依然可以使用next函数和for循环取值

第一种生成器
类似于列表推导式,只是将列表推导式的[ ]改为()
# 列表推导式
my_list = [i * 2 for i in range(5)]
print(my_list)

# 创建生成器
my_generator = (i * 2 for i in range(5))
print(my_generator)

# next获取生成器下一个值
# value = next(my_generator)
# print(value)

for value in my_generator:
    print(value)
    
 # 执行结果  
[0, 2, 4, 6, 8]
<generator object <genexpr> at 0x101367048>
0
2
4
6
8
第二种生成器
在def函数里面看到有yield关键字那么就是生成器
def fibonacci(num):
    a = 0
    b = 1
    # 记录生成fibonacci数字的下标
    current_index = 0
    print("--11---")
    while current_index < num:
        result = a
        a, b = b, a + b
        current_index += 1
        print("--22---")
        # 代码执行到yield会暂停,然后把结果返回出去,下次启动生成器会在暂停的位置继续往下执行
        yield result
        print("--33---")

fib = fibonacci(5)
value = next(fib)
print(value)
value = next(fib)
print(value)

value = next(fib)
print(value)

# for value in fib:
#     print(value)

# 执行结果
--11---
--22---
0
--33---
--22---
1
--33---
--22---
1

猜你喜欢

转载自blog.csdn.net/weixin_43733896/article/details/84309450