社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

二十、深入Python迭代器和生成器

Python开发 • 4 年前 • 325 次点击  
👇👇关注后回复 “进群” ,拉你进程序员交流群👇👇

作者丨小sen

来源丨Python之王


「@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))判断是不是可迭代对象。还是一种通过Iterableisinstance方法联合使用,进行判断。

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 1in 
StopIteration

生成器

那么什么又是生成器,和迭代器又有什么关系?

其实,生成器也是迭代器,但更加优雅。使用生成器,我们可以实现与迭代器相同的功能,但不必在类中编写iter()和next()函数

「我觉得生成器就是一个迭代器的例子。」,如果说迭代器是人,那么生成器就人中的一类人,比如黄人。

为什么会出来一个生成器,其实很简单声明一个迭代器很简单,但是很容易造成内存不够。生成器不会将集合中所有的元素都加载到内存。

比如下图(i for i in range(1000000000)通过元组方式生成生成器。如果使用迭代器,那么当声明迭代器就运行不了了。

[i for i in range(1000000000] 它本是一个迭代器,但因占用的内存太大了,跑不起来,于是古人引出了生成器的概念,当你用的时候,再加载到内存空间中。

在声明生成器中,还有一种方法通过yield关键字。

yieldreturn的区别在于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

Reference

[1]

传送门~: https://github.com/MaoliRUNsen/runsenlearnpy100


-End-

最近有一些小伙伴,让我帮忙找一些 面试题 资料,于是我翻遍了收藏的 5T 资料后,汇总整理出来,可以说是程序员面试必备!所有资料都整理到网盘了,欢迎下载!

点击👆卡片,关注后回复【面试题】即可获取

在看点这里好文分享给更多人↓↓

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/113854
 
325 次点击