列表,我们使用for循环来取值,我们把每个值都取到,不需要关心每一个值的位置,因为只能顺序的取值,并不能跳过任何一个去取其他位置的值。那么我们为什么可以使用for循环来取值,for循环内部是怎么工作的呢?

迭代器:

示例1:

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

如果我们换成:

for i in 1234:
    print(i)

python for生成dict python for i in dict_python for生成dict

iterable: 可重复的,可迭代的。

什么叫可迭代的?

字符串、列表、元组、字典、集合、文件、range、enumerate(枚举)都可以被for循环,说明它们是可迭代的。

from collections.abc import Iterable

l = [1, 2, 3, 4]
t = (1, 2, 3, 4)
d = {1: 2, 3: 4}
s = {1, 2, 3, 4}

# 判断对象是否是可迭代对象
print(isinstance(l, Iterable))
print(isinstance(t, Iterable))
print(isinstance(d, Iterable))
print(isinstance(s, Iterable))

判断对象是否是可迭代对象。

可以将某个数据集内的数据“一个挨着一个地取出来”, 就叫做迭代。

可迭代协议:

假如我们自己写一个数据类型,我们希望这个数据类型里面的东西可以使用for被一个一个地取出来,那么我们就必须满足for的要求,这个要求就叫做“协议”。

可以被迭代要满足的要求就叫做可迭代协议。可迭代协议非常简单,就是内部实现了__iter__方法。要想可迭代,内部必须有一个__iter__方法:

print(dir([1, 2]))
print(dir((1, 2)))
print(dir({1: 2}))
print(dir({1, 2}))

dir功能:就是告诉我类型拥有的所有方法。

双下划线的方法:双下方法。双下方法是不直接被我们调用的。正常情况下,我们只要学习不带下划线的方法。

python for生成dict python for i in dict_迭代器_02

print('__iter__' in dir(int))
print('__iter__' in dir(bool))
print("__iter__" in dir(str))
print('__iter__' in dir(list))
print('__iter__' in dir(dict))

结果:

python for生成dict python for i in dict_迭代_03

只要是能被for循环的数据类型,就一定能拥有__iter__方法,就是可迭代的。只要有__iter__方法的,就一定是可迭代的。

然后,我们打印一个东西:

print([].__iter__())

 结果:

python for生成dict python for i in dict_迭代_04

那么, __iter__做了什么事情呢?得到了一个list_iterator。

迭代器的概念:一个列表执行了__iter__()之后的返回值就是一个迭代器。

iterator:迭代器

迭代器协议:

在列表迭代器中多了三个方法:

iter_l = [1,2,3,4,5,6].__iter__()
#获取迭代器中元素的长度
print(iter_l.__length_hint__())
#根据索引值指定从哪里开始迭代
print('*',iter_l.__setstate__(4))
#一个一个的取值
print('**',iter_l.__next__())
print('***',iter_l.__next__())

在for循环中,就是在内部调用了__next__()方法才能取到一个一个的值。

只要含有__iter__方法的都是可迭代的,就叫可迭代协议。

迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。

print('__iter__' in dir([].__iter__()))
print('__next__' in dir([].__iter__()))
from collections.abc import Iterable
from collections.abc import Iterator

# 判断列表是不是一个可迭代器
print(isinstance([], Iterator))

# 判断列表是不是可迭代的
print(isinstance([], Iterable))

我们自己创建一个类A(自定义数据类型):

from collections.abc import Iterable
from collections.abc import Iterator


class A:
    def __iter__(self): pass
    def __next__(self): pass


a = A()


print(isinstance(a, Iterator))
print(isinstance(a, Iterable))

我们让一个类拥有__iter__和__next__方法。这个就是迭代器协议的内容。

只有可迭代对象的时候,才能用for。

当我们遇到一个新的变量,不能确定能不能for循环的时候,就判断它是否可迭代。

那为什么要有for循环?

for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器,然后使用迭代器协议去实现循环访问,这样所有的对象就都可以通过for循环来遍历了。

for i in l:

# iterator = l.__iter__()

# iterator.__next__()

迭代器的好处:

1)从容器类型中一个个地取值,会把所有的值都取到;

2)节省内存空间;