Day 20 迭代器、生成器

一、 迭代器

1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退)

2.可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个iter()方法)

3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象

二、python中for循环机制

for循环的本质:循环所有对象,全都是使用迭代器协议。

正本清源: 
很多人会想,for循环的本质就是遵循迭代器协议去访问对象,那么for循环的对象肯定都是迭代器了啊,没错,那既然这样,for循环可以遍历(字符串,列表,元组,字典,集合,文件对象),那这些类型的数据肯定都是可迭代对象啊?但是,我他妈的为什么定义一个列表l=[1,2,3,4]没有l.next()方法。

(字符串,列表,元组,字典,集合,文件对象)这些都不是可迭代对象,只不过在for循环式,调用了他们内部的iter方法,把他们变成了可迭代对象 
然后for循环调用可迭代对象的next方法去取值,而且for循环会捕捉StopIteration异常,以终止迭代

循环访问方式
#for循环l本质就是遵循迭代器协议的访问方式,先调用diedai_l=l.__iter__()方法,或者直接diedai_l=iter(l),然后依次执行diedai_l.next(),直到for循环捕捉到StopIteration终止循环
  #for循环所有对象的本质都是一样的原理

for循环

序列类型字符串,列表,元组都有下标,你用上述的方式访问,perfect!但是你可曾想过非序列类型像字典,集合,文件对象的感受,for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,即在遍历之前,先调用对象的iter方法将其转换成一个迭代器,然后使用迭代器协议去实现循环访问,这样所有的对象就都可以通过for循环来遍历了,而且你看到的效果也确实如此,这就是无所不能的for循环

生成器

什么是生成器? 
可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要调用自己内置的iter方法),所以生成器就是可迭代对象

生成器分类及在python中的表现形式: 
(Python有两种不同的方式提供生成器) 
1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行 
2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表

为何使用生成器之生成器的优点 
(Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。这也是生成器的主要好处。

生成器小结: 
1.是可迭代对象 
2.实现了延迟计算,省内存啊 
3.生成器本质和其他的数据类型一样,都是实现了迭代器协议,只不过生成器附加了一个延迟计算省内存的好处,其余的可迭代对象可没有这点好处。

生成器函数

生成器表达式和列表解析

1.把列表解析的[]换成()得到的就是生成器表达式 
2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存 
3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和

生成器总结:

语法上和函数类似:生成器函数和常规函数几乎是一样的。它们都是使用def语句进行定义,差别在于,生成器使用yield语句返回一个值,而常规函数使用return语句返回一个值 
自动实现迭代器协议:对于生成器,Python会自动实现迭代器协议,以便应用到迭代背景中(如for循环,sum函数)。由于生成器自动实现了迭代器协议,所以,我们可以调用它的next方法,并且,在没有值可以返回的时候,生成器自动产生StopIteration异常 
状态挂起:生成器使用yield语句返回一个值。yield语句挂起该生成器函数的状态,保留足够的信息,以便之后从它离开的地方继续执行。

优点一:生成器的好处是延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。 
优点二:生成器还能有效提高代码可读性。

这里,至少有两个充分的理由说明 ,使用生成器比不使用生成器代码更加清晰: 
使用生成器以后,代码行数更少。大家要记住,如果想把代码写的Pythonic,在保证代码可读性的前提下,代码行数越少越好 
不使用生成器的时候,对于每次结果,我们首先看到的是result.append(index),其次,才是index。也就是说,我们每次看到的是一个列表的append操作,只是append的是我们想要的结果。使用生成器的时候,直接yield index,少了列表append操作的干扰,我们一眼就能够看出,代码是要返回index。 
这个例子充分说明了,合理使用生成器,能够有效提高代码可读性。只要大家完全接受了生成器的概念,理解了yield语句和return语句一样,也是返回一个值。那么,就能够理解为什么使用生成器比不使用生成器要好,能够理解使用生成器真的可以让代码变得清晰易懂。

注意事项:生成器只能遍历一次

知识点程序:

  1 #! /usr/bin/env python
  2 # -*- coding: utf-8 -*-
  3 # __author__ = "DaChao"
  4 # Date: 2017/6/15
  5
  6 ######################################################
  7 #迭代器
  8 ######################################################
  9
 10 # dic = {"a":1,"b":2,"c":3}
 11
 12 # aa = dic.__iter__()
 13 # print(aa.__next__())
 14 # print(aa.__next__())
 15 # print(aa.__next__())
 16 # print(aa.__next__())
 17
 18 # lit = [‘a‘,‘b‘,‘c‘]
 19 #
 20 # bb = lit.__iter__()
 21 # print(bb.__next__())
 22 # print(bb.__next__())
 23 # print(bb.__next__())
 24 # print(bb.__next__())
 25
 26
 27 ######################################################
 28 #修饰器引进参数 Y
 29 ######################################################
 30
 31 # def deco(auth_type = "file"):
 32 #     def auth(func):
 33 #         def wrapper(*args,**kwargs):
 34 #             if auth_type == "file":
 35 #                 print("文件的认证方式!")
 36 #             elif auth_type == "Idap":
 37 #                 print("Idap的认证方式!")
 38 #             elif auth_type == "mysql":
 39 #                 print("mysql的认证方式!")
 40 #             else:
 41 #                 print("不知道的认证方式!")
 42 #         return wrapper
 43 #     return auth
 44 # #
 45 # @deco()        #引进参数,如例,默认为auth_type="file"
 46 # def index():
 47 #     print("Welcome to index!")
 48 #
 49 # index()
 50
 51 ######################################################
 52 #制作缓存
 53 ######################################################
 54
 55 # import os
 56 # from urllib.request import urlopen
 57 #
 58 # cache_path = r"D:\Python\study\Day 8\cache.txt"
 59 # def cache(func):
 60 #     def wrapper(*args,**kwargs):
 61 #         if os.path.getsize(cache_path):   #有缓存
 62 #             with open(cache_path,"rb") as f:
 63 #                 res = f.read()
 64 #         else:
 65 #             res = func(*args,**kwargs)   #下载
 66 #             with open(cache_path,"wb") as f:   #制作缓存
 67 #                 f.write(res)
 68 #         return res
 69 #     return wrapper
 70 #
 71 # @cache
 72 # def get(url):
 73 #     ‘‘‘
 74 #     读取网站并返回其内容
 75 #     :param url:
 76 #     :return:
 77 #     ‘‘‘
 78 #     return urlopen(url).read()    #注意指令,读出内容并返回
 79 #
 80 # print(get("https://www.yinxiang.com/webclipper/guide/"))
 81
 82 ######################################################
 83 #从数据库读取用户名和密码 Y
 84 ######################################################
 85
 86 # aaa_path = r"D:\Python\study\Day 8\aaa.txt" # r后面内容不转义
 87 #
 88 # def check(func):
 89 #     def wrapper(*args,**kwargs):
 90 #         usrname = input("Please input your name: ").strip()
 91 #         echo = input("Please input your echo: ").strip()
 92 #         with open(aaa_path,"r",encoding="utf-8") as f:
 93 #             usr_dic = eval(f.read())
 94 #         if usrname in usr_dic and echo == usr_dic[usrname]:
 95 #             print("Loggin successful!")
 96 #             func(*args,**kwargs)
 97 #         else:
 98 #             print("Loggin error!")
 99 #     return wrapper
100 #
101 # @check
102 # # def index():
103 # #     print("Welcome to my world!")
104 #
105 # # index()
106 # def index(name):
107 #     print("Welcome to %s`s world!" %name)
108 #
109 # index("dachao")
110
111
112 ######################################################
113 #文件模拟数据存取 Y
114 ######################################################
115
116 # usr_dic = {
117 #     "egon":"123",
118 #     "alex":"alex3714",
119 #     "wupeiqi":"321",
120 #     "yuanhao":"123123"
121 # }
122 #
123 # with open("aaa.txt","w",encoding="utf-8") as f:
124 #     f.write(str(usr_dic))                     #write 只能写入字符串
125 #
126 # with open("aaa.txt","r",encoding="utf-8") as f:
127 #     res = f.read()
128 #     # print(res,type(res))
129 #     usr_dic=eval(res)
130 #     print(usr_dic,type(usr_dic))
131
132
133
134 ######################################################
135 #eval功能:提取字符串命令并执行结果 Y
136 ######################################################
137 # eval("print(‘hello world‘)")
138
139
140
141 ######################################################
142 #注释修改功能 Y
143 ######################################################
144 # from functools import wraps        #调用内部函数 wraps
145 #
146 # def check_xiushi(func):
147 #     ‘‘‘
148 #     修饰器:check_xiushi
149 #     :param func:
150 #     :return:
151 #     ‘‘‘
152 #     @wraps(func)                    #必须在闭包上面,实现保留原始func功能的作用
153 #     def wrapper():
154 #         ‘‘‘
155 #         修饰器:闭包函数。
156 #         :return:
157 #         ‘‘‘
158 #         print("我是修饰器!")
159 #         func()
160 #     # wrapper.__doc__ = func.__doc__     #在调用阶段,实现
161 #     return wrapper
162 #
163 # @check_xiushi
164 # def check():
165 #     ‘‘‘
166 #     check function
167 #     :return:
168 #     ‘‘‘
169 #     print("Hello world!")
170
171 # check()
172 # print(check.__doc__)
173 # print(help(check))
174
175
176 # print(check.__name__)
177 # check.__wrapped__()           #调用wraps后,执行原始check函数

knowledge

作业:

 1 #! /usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 # __author__ = "DaChao"
 4 # Date: 2017/6/15
 5
 6 # 四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
 7 #     注意:从文件中读出字符串形式的字典,可以用eval(‘{"name":"egon","password":"123"}‘)转成字典格式
 8
 9 # cache_path = r"D:\Python\study\Day 8\cache.txt"
10 #
11 # login_dic = {
12 #     "usr":None,
13 #     "status":False
14 # }
15 #
16 #
17 # def check(func):
18 #     ‘‘‘
19 #     用户登录验证,一次成功,后期不需要再次验证!
20 #     :param func:
21 #     :return:
22 #     ‘‘‘
23 #     def wrapper():
24 #         if login_dic["usr"] and login_dic["status"]:
25 #             res = func()
26 #             return res
27 #         usrname = input("Please input your name: ")
28 #         echo = input("Please input your echo: ")
29 #         with open(cache_path,"r",encoding="utf-8") as f:
30 #             usr_dic = eval(f.read())
31 #         if usrname in usr_dic and echo == usr_dic[usrname]:
32 #             login_dic["usr"] = usrname
33 #             login_dic["status"] = True
34 #             print("Loggin successful!")
35 #             func()
36 #         else:
37 #             print("Loggin err!")
38 #     return wrapper
39 #
40 # @check
41 # def index():
42 #     print("Welcome to my world!")
43 # @check
44 # def index1():
45 #     print("hahahaha")
46
47 # 五:编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
48 # 六:为题目五编写装饰器,实现缓存网页内容的功能:
49 #     具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,
50 #     否则,就去下载,然后存到文件中
51
52 # import os
53 # from urllib.request import urlopen
54 #
55 # cache_path = r"D:\Python\study\Day 8\cache.txt"
56 # def cache(func):
57 #     def wrapper(*args,**kwargs):
58 #         if os.path.getsize(cache_path):   #有缓存
59 #             with open(cache_path,"rb") as f:
60 #                 res = f.read()
61 #         else:
62 #             res = func(*args,**kwargs)   #下载
63 #             with open(cache_path,"wb") as f:   #制作缓存
64 #                 f.write(res)
65 #         return res
66 #     return wrapper
67 #
68 # @cache
69 # def get(url):
70 #     ‘‘‘
71 #     读取网站并返回其内容
72 #     :param url:
73 #     :return:
74 #     ‘‘‘
75 #     return urlopen(url).read()    #注意指令,读出内容并返回
76 #
77 # print(get("https://www.yinxiang.com/webclipper/guide/"))
78
79 # 七:还记得我们用函数对象的概念,制作一个函数字典的操作吗,
80 # 来来来,我们有更高大上的做法,在文件开头声明一个空字典,然后在每个函数前加上装饰器,完成自动添加到字典的操作

work

时间: 2024-10-20 22:58:34

Day 20 迭代器、生成器的相关文章

Day4 - 迭代器&生成器、装饰器、Json & pickle 数据序列化、软件目录结构规范

---恢复内容开始--- 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 需求:列表a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求把列表里的每个值加1 1 a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 2 b = [] 3 for i in a: 4 b.append(i+1) 5 a = b 6 print(a) 普通青

Python(四)装饰器、迭代器&生成器、re正则表达式、字符串格式化

本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能. 先定义一个基本的装饰器: ########## 基本装饰器 ########## def orter(func):    #定义装饰器     de

Python装饰器、迭代器&生成器、re正则表达式、字符串格式化

Python装饰器.迭代器&生成器.re正则表达式.字符串格式化 本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能. 先定义一个基本的装饰器: ########## 基本装饰器 ########

python之迭代器生成器和内置函数,匿名函数

今天学习了迭代器生成器以及内置函数和匿名函数,说实话有些懵圈,有些难度了. 一.迭代器和生成器 1.如何从列表.字典中取值的: index索引 for循环 凡是可以使用for循环取值的都是可迭代的 (1)可迭代协议:内部含有__iter__方法的都是可迭代的 (2)迭代器协议:内部含有__iter__方法和__next__方法的都是迭代器 什么是可迭代的:内部含有__iter__方法的都是可迭代的 什么是迭代器:迭代器=iter(可迭代的),自带一个__next__方法 可迭代最大的优势:节省内

python 【迭代器 生成器 列表推导式】

python [迭代器  生成器  列表推导式] 一.迭代器 1.迭代器如何从列表.字典中取值的 index索引 ,key for循环凡是可以使用for循环取值的都是可迭代的可迭代协议 :内部含有__iter__方法的都是可迭代的迭代器协议 :内部含有__iter__方法和__next__方法的都是迭代器 print(dir([1,2,3])) lst_iter = [1,2,3].__iter__() print(lst_iter.__next__()) print(lst_iter.__ne

函数嵌套 ,名称空间与作用域 ,闭包函数 ,装饰器 ,迭代器, 生成器 三元表达式,列表解析,生成器表达式 递归与二分法, 内置函数

函数嵌套名称空间与作用域闭包函数装饰器迭代器生成器三元表达式,列表解析,生成器表达式递归与二分法内置函数--------------------------------------------函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数函数的嵌套定义:在一个函数的内部,又定义另外一个函数def max(x,y): if x>y: return x else: return ydef max1(a,b,c,d): res=max(a,b) res2=max(res,c) res3=ma

[python]--迭代器,生成器补充

在python中,list,string,dict都是可迭代对象,可以通过for语句遍历. 迭代器 迭代器对象要求支持迭代器协议的对象,在python中,支持迭代器协议就算实现对象的__iter__()和next()方法.其中__iter__()方法返回迭代器对象本身; next()方法返回容器的下一个元素,在结尾时引发StopIteration异常 __iter__()和next()方法 这两个方法是迭代器最基本的方法,一个用来获得迭代器对象,一个用来获取容器中的下一个元素. 对于可迭代对象,

day4装饰器-迭代器&&生成器

一.装饰器 定义:本质是函数,(装饰其他函数)就是为其它函数添加附加功能 原则:1.不能修改被装饰的函数的源代码 2.不能修改被装饰的函数的调用方式 实现装饰器知识储备: 1.函数及“变量” 2.高阶函数 a.把一个函数名当做实参传给另一个函数(在不修改被装饰器函数源代码的情况下为其添加新功能) b.返回值中包含函数名 3.嵌套函数 高阶函数+嵌套函数 = 装饰器 延迟3秒 import time def test1(): time.sleep(3) print('in the test1')

函数---迭代器&生成器&列表解析&三元表达式

可迭代对象:obj.__iter__ 迭代器:iter1=obj.__iter() 1iter1.__next__ 2iter2.__next__ 迭代器: 优点:不依赖索引 惰性计算,节省内存 缺点: 不如按照索引的取值方便 一次性,只能往后取,不能回退 迭代器的应用: 提供了一种不依赖索引的统一的迭代方法 惰性计算,比如取文件的每一行 判断可是否是可迭代对象和迭代器 from collections import Iterable, Iterator # 导入模块功能 isinstance(

Python 迭代器&生成器,装饰器,递归,算法基础:二分查找、二维数组转换,正则表达式,作业:计算器开发

本节大纲 迭代器&生成器 装饰器  基本装饰器 多参数装饰器 递归 算法基础:二分查找.二维数组转换 正则表达式 常用模块学习 作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式,运算后得出结果,结果必须与真实的计算器所得出的结果一致 迭代器&