我的编程空间,编程开发者的网络收藏夹
学习永远不晚

python进阶之生成器

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

python进阶之生成器

迭代器

  什么叫迭代

    可以被for循环的就说明他们是可迭代的,比如:字符串,列表,字典,元祖,们都可以for循环获取里面的数据

  下面我们看一个代码:  

1 number = 12345
2 for i in number:
3     print(i)
4 输出:
5 Traceback (most recent call last):
6   File "D:**.py", line 272, in <module>
7     for i in number:
8 TypeError: 'int' object is not iterable

报错信息是说:int类型不可迭代,不能使用循环取每个数据。 那么我们又怎么说 字符串,列表,字典,元祖是可迭代的呢?

 1 from collections import Iterable
 2 
 3 l = [1, 2, 3, 4]
 4 t = (1, 2, 3, 4)
 5 d = {1: 2, 3: 4}
 6 s = {1, 2, 3, 4}
 7 
 8 print(isinstance(l, Iterable)) # 判断是否是可迭代
 9 print(isinstance(t, Iterable))
10 print(isinstance(d, Iterable))
11 print(isinstance(s, Iterable))
True
True
True
True

再从字面上理解一下,其实迭代就是我们刚刚说的,可以将某个数据集内的数据“一个挨着一个的取出来”,就叫做迭代

  什么叫可迭代协议   

    我们现在是从结果分析原因,能被for循环的就是“可迭代的”,但是如果正着想,for怎么知道谁是可迭代的呢?

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

可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__iter__方法。

 

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

 

输出:

['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']

 现在我们可以知道:可以被for循环的都是可迭代的,要想迭代内部必须有一个__iter__方法。

那么这个方法又干了些什么事情呢?

print([1,2].__iter__())

结果
<list_iterator object at 0x1024784a8>

 看结果,应该是得到了一个可迭代对象list_iterator 就是一个迭代器,现在我们知道这个列表有一个迭代器了

1 print(set(dir([1,2].__iter__()))-set(dir([1,2])))
2 
3 输出:
4 {'__next__', '__setstate__', '__length_hint__'}

我们获取了列表迭代器3个方法,那么这些方法又干了什么呢? 我们只说__next__

1 iter = [1,2,3,4,5,6].__iter__()
2 
3 #一个一个的取值
4 print(iter.__next__())
5 print(iter.__next__())
6 输出:
7 1
8 2

我们看到的结果是取到了列表的前两个元素,所以说,for循环就是调用了内部的__next__方法实现遍历的,我们可以不使用for循环,直接调用这个方法就可以实现遍历列表元素

但是如果我们列表有3个元素我们调用__next__4次就会抛出异常StopIteration,因为没有第4个元素

 1 iter = [1,2,3].__iter__()
 2 
 3 #一个一个的取值
 4 print(iter.__next__())
 5 print(iter.__next__())
 6 print(iter.__next__())
 7 print(iter.__next__())
 8 输出:
 9 Traceback (most recent call last):
10 1
11   File "D:/pythonSeleniumTestCode/pythonStu/python练习100例.py", line 295, in <module>
12 2
13     print(iter.__next__())
14 3
15 StopIteration

现在我们把这个异常处理一下

1 iter = [1,2,3].__iter__()
2 while 1:
3     try:
4         item = iter.__next__()
5         print(item)
6     except StopIteration:
7         break

那现在我们就使用while循环实现了原本for循环做的事情,我们是从谁那儿获取一个一个的值呀?是不是就是l_iter?好了,这个l_iter就是一个迭代器。

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

现在我们已经大概有了迭代器的印象,那么我们再来看看生成器是个什么鬼!

 

生成器:

  我们知道的迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。

如果在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器

 

Python中提供的生成器:

 

  1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行

 

  2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表

 

生成器Generator:

 

  本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)

 

  特点:惰性运算,开发者自定义

看实例代码:

1 def genrator():
2     for i in range(1, 5):
3         yield ('正在生成数字{}'.format(i)) # 
4 
5 yie = genrator()
6 for i in yie:
7     print(i)

输出:

正在生成数字1
正在生成数字2
正在生成数字3
正在生成数字4

 如果我只想生成2个数字我们该怎么实现呢?是不是这样?

1 yie = genrator()
2 num = 0
3 for i in yie:
4     print(i)
5     num+=1
6     if num == 2:
7         break

输出:

正在生成数字1
正在生成数字2

 现在们已经生成了2个数字了,那么我想接着生成,还可不可以呢?

 1 def genrator():
 2     for i in range(1, 5):
 3         yield ('正在生成数字{}'.format(i))
 4 
 5 yie = genrator()
 6 num = 0
 7 for i in yie:
 8     print(i)
 9     num+=1
10     if num == 2:
11         print('我只能生成2个数')
12         break
13 for i in yie:
14     print(i)

输出:

正在生成数字1
正在生成数字2
我只能生成2个数
正在生成数字3
正在生成数字4

 结果我们分析出,生成2个数以后既然还可以接着原来的生成。

下面我们再来看看到底怎么使用生成器,我现在要监听一个文件的输入,如果文件中增加了数据,我就在控制到输出增加的内容

1 def tail(filename):
2     f =  open(filename, encoding='utf-8')
3     while True:
4         line = f.readline()
5         if line.strip():
6             print(line.strip())
7 if __name__ == '__main__':
8     tail('A')

只要我再A文件中写入一行数据,那么控制到就会输出这行数据,我们就达到了监听文件的作用,是不是还挺好用的!

结论:

  生成器好处

    1.不会占用太多的内存,我们需要生成一个数就生成,不需要就不用叫他生成

    2.延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。

  什么是生成器

    只要含有yield关键字的函数都是生成器函数, 且yield不能与return一起使用,二者存一,而且只能写在函数的内部

    *生成器只能取一次值,取完就没了

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

python进阶之生成器

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

python进阶之生成器

迭代器  什么叫迭代    可以被for循环的就说明他们是可迭代的,比如:字符串,列表,字典,元祖,们都可以for循环获取里面的数据  下面我们看一个代码:  1 number = 123452 for i in number:3
2023-01-30

day14-生成器进阶

'''def generator(): print(123) yield 1 print(456) yield 2 print(789)g = generator()ret = g.__next__()prin
2023-01-31

老生常谈Python进阶之装饰器

函数也是对象 要理解Python装饰器,首先要明白在Python中,函数也是一种对象,因此可以把定义函数时的函数名看作是函数对象的一个引用。既然是引用,因此可以将函数赋值给一个变量,也可以把函数作为一个参数传递或返回。同时,函数体中也可以再
2022-06-04

Python进阶之列表推导与生成器表达式详解

这篇文章主要为大家详细介绍了Python中列表推导与生成器表达式的相关知识,文中的示例代码讲解详细,具有一定的参考价值,需要的可以参考一下
2023-05-16

python进阶之装饰器

一.无参装饰器问题:如何计算一段程序的运行时间?先看一段简单代码:1 import time2 def func():3 start = time.time() # 记录程序开始时间4 time.sleep(5)5
2023-01-30

Python之函数进阶

一.形参的动态参数: 动态参数,用于参数不确定时用. 格式:def fun (*args)fun(args)1. 动态接收位置参数:动态参数必须在位置参数后.列子1.假如参数不确定时,如下的列子,每人饭量不一样,吃的种类不一样,此时用到动态
2023-01-30

JavaScript使用高阶生成器进行过滤以生成素数

本文介绍了如何使用JavaScript的高阶生成器和filter函数生成素数。使用高阶生成器可以按需生成值,提高内存效率。通过使用primeGenerator函数生成素数序列,并使用isPrime过滤函数过滤该序列,可以高效地实现素数生成。这种方法代码可读性高、复用性强、灵活且高效。
JavaScript使用高阶生成器进行过滤以生成素数
2024-04-02

Python之yield生成器

1、对比range和xrange的区别:>>> print range(10)[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> print xrange(10)xrange(10)range()和xrange()的区别在于
2023-01-31

Python 3 之 生成器详解

------ 生成器 ------------------------------------------------------------------如今Python对延迟提供更多的支持——它提供了工具在需要的时候才产生结果,而不是立即
2023-01-31

Python基础之变量进阶

变量的引用变量和数据都是保存在内存中的;在python中函数的参数传递以及返回值都是靠引用传递的。函数引用的概念在python中变量和数据时分开存储的;数据保存在内存中的一个位置;变量保存着数据在内存中的地址;变量中记录数据的地址,就叫做引
2023-01-31

Python进阶之网络编程

网络通信使用网络的目的把多方链接在一起,进行数据传递;网络编程就是,让不同电脑上的软件进行数据传递,即进程间通信;ip地址ip地址概念和作用IP地址是什么:比如192.168.1.1 这样的一些数字;ip地址的作用:用来在电脑中 标识唯一一
2023-01-31

Python序列操作之进阶篇

简介 Python 的序列(sequence)通常指一个可迭代的容器,容器中可以存放任意类型的元素。列表和元组这两种数据类型是最常被用到的序列,python内建序列有六种,除了刚刚有说过的两种类型之外,还有字符串、Unicode字符串、bu
2022-06-04

python进阶之正则表达式

概念:  正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。目的?      给定一个正则表达式和另一个字符串,我们可以达
2023-01-30

Python全栈开发之Django进阶

No.1 静态文件处理项目中CSS、JS、图片都属于静态文件,一般会将静态文件存到一个单独目录中,便于管理,在HTML页面调用时,需要指定静态文件的路径,Django提供了一种解析静态文件的机制,文件可以放在项目目录下,也可以放在应用目录下
2023-01-31

python装饰器进阶

目录 装饰器进阶 1. 被装饰的函数有多个参数。 2. 被装饰的函数有返回值 3.在函数中嵌入装饰器 4. 装饰器类 总结
2023-01-30

Python学习之迭代器和生成器

迭代器在Python如果一个对象可被循环(遍历)该对象中每一个元素的过程叫做迭代。例如 ,字典、字符串、列表、元祖、集合等。他们可被迭代的原因是,都有一个共同的内置函数__iter__。通过执行内置对象的__next__函数,可以依次打印该
2023-01-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录