「@Author:Runsen」
学习python的过程中,迭代器与生成器是绕不开的话题, 什么是迭代器和生成器呢?
下面我们来了解一下什么是迭代。但在了解迭代器之前,首先需要知道什么是容器。
容器
正所谓:一切都是对象,对象的抽象就是类,而对象的集合就是容器。
容器,就是有多个对象组成的东西。
比如:列表[0,1,2],元组(1,2,3),字典{’0:'0','1':"1'}集合{1,2,3}都是容器。
「所有的容器都是可迭代对象,也就是可以使用for循环遍历元素。」
# 1、for 循环迭代字符串, 字符串之间使用空格连接
for char in 'RUNSEN':
print(char, end=' ')
输出如下:
R U N S E N
# 2、for 循环迭代 list 列表,列表元素之间使用空格连接
list1 = [i for i in range(5)] # 这里使用了列表生成表达式
for num in list1:
print(num, end=' ')
输出如下:
0 1 2 3 4
# 3、for 循环迭代 dict (字典)
dict = {'name': 'Runsen', 'age': '21', 'sex': '男'}
# 迭代 dict 中的 key(默认是迭代key)
for key in dict:
print(key, end=' ')
for value in dict.values():
print(value, end=' ')
输出如下:
name age sex
Runsen 21 男
# 4、list 中一个元素中还有多个元素
for x, y in [(1, 'a'), (2, 'b'), (3, 'c')]:
print(x, y)
输出如下:
1 a
2 b
3 c
可迭代对象
所有的容器都是可迭代对象(iterable),从专业角度来讲,只要:内部含有__iter__方法的对象,就是可迭代对象。
因此,我只要使用print('__iter__' in dir(XX)),就能判断XX是不是可迭代对象。
人们常说:列表、元组、字典、字符串都是可迭代对象。数字、布尔值都是不可迭代的。我一试便知。
list,dict(keys(),values(),items()),tuple,str,set,range, 文件句柄(待定)
print('__iter__' in dir(list))
print('__iter__' in dir(tuple))
print('__iter__' in dir(dict))
print('__iter__' in dir(set))
print('__iter__' in dir(str))
print('__iter__' in dir(int))
print('__iter__' in dir(bool))
print('__iter__' in dir([1,2,3]))
输出如下:
True
True
True
True
True
False
False
True
除了print('__iter__' in dir(XX))判断是不是可迭代对象。还是一种通过Iterable和isinstance方法联合使用,进行判断。
from collections import Iterable
print(isinstance('abc', Iterable))
print(isinstance({1, 2, 3}, Iterable))
print(isinstance(1, Iterable))
输出如下:
True
True
False
「注意:list,string,tuple,dict 都属于可迭代对象,但不是迭代器」
迭代器
迭代器(iterator)只是提供了一个 next 的方法。调用这个方法后,你要么得到这个可迭代对象的下一个对象,要么得到一个 StopIteration的错误。
那么,如何声明一个可迭代对象,可以通过__iter__() 来生成可迭代对象,前提是__iter__()传入的参数是容器。
你看下图iter(111)是不是报错了。
因为111不能遍历,所以iter(111)直接报错。
取值
上面说过:迭代器提供了一个next方法,调用这个方法,得到了容器的下一个对象或者一个stopiteration 的报错,具体代码如下所示。
>>>a = iter("123")
>>>next(a)
'1'
>>>next(a)
'2'
>>>next(a)
'3'
>>>next(a)
Traceback (most recent call last):
File "", line 1, in
StopIteration
生成器
那么什么又是生成器,和迭代器又有什么关系?
其实,生成器也是迭代器,但更加优雅。使用生成器,我们可以实现与迭代器相同的功能,但不必在类中编写iter()和next()函数
「我觉得生成器就是一个迭代器的例子。」,如果说迭代器是人,那么生成器就人中的一类人,比如黄人。
为什么会出来一个生成器,其实很简单声明一个迭代器很简单,但是很容易造成内存不够。生成器不会将集合中所有的元素都加载到内存。
比如下图(i for i in range(1000000000)通过元组方式生成生成器。如果使用迭代器,那么当声明迭代器就运行不了了。
[i for i in range(1000000000] 它本是一个迭代器,但因占用的内存太大了,跑不起来,于是古人引出了生成器的概念,当你用的时候,再加载到内存空间中。
在声明生成器中,还有一种方法通过yield关键字。
yield和return的区别在于yield并没有终止函数,而return返回值后不再执行函数内代码。
对于yield,在scrapy用的多,然后我在其他地方没有见到过。
引用yield,带yield的函数就叫做生成器,具体示例如下所示。
def test():
yield 1
yield 2
yield 3
t = test()
print(next(t))#output:1
print(next(t))#output:2
print(next(t))#output:3
print(next(t))#output:Traceback (most recent call last):StopIteration
今天也学到了很多东西呢,明天有什么新知识呢?真期待鸭。如果喜欢文章可以关注我哦~
❝
本文已收录 GitHub,传送门~[1] ,里面更有大厂面试完整考点,欢迎 Star。
❞
Reference
[1]
传送门~: https://github.com/MaoliRUNsen/runsenlearnpy100