day13: 迭代器和生成器
1,思考所有可以被for循环的:list,tuple,set,dict,range,enumerate,f,str,差不多了,为何这些数据类型可以被for循环呢?
2,一个标准的装饰器函数
from functools import wraps
def wrapper(f):
@wraps(f)
def inner(*args,**kwargs):
# 被装饰函数调用之前添加的功能
ret = f(*args,**kwargs)
# 被装饰函数调用之后添加的功能
return ret
return inner @wrapper
def func():
print("i am func") func()
3,查看一个变量或者是数据类型的所有方法dir
print(dir([])) # 告诉我字典拥有的所有方法
[].__add__() # 这些方法都可以通过点来调用
4,双下方法,一般双下方法我们不会自己去调用,通常是执行其他操作的时候,自动调用的,也叫做魔法方法
# 运行加操作的时候,会自动调用双下add方法
print([1]+[2])
print([1].__add__([2]))
5,结论,只要是可以被for循环的就有__iter__方法
# 我想查看一下这些数据有哪些共同的方法
# ret = set(dir([]))&set(dir({}))&set(dir(''))&set(dir(range(10))) # 求交集
# print(ret) # 发现了一个和可迭代的Iterable很像的双下函数__iter__ # 那我们来查看一下intl类型是否有这个函数
print("__iter__" in dir(int)) #结果为false
print("__iter__" in dir(bool))
# 看看其他的类型有没有这个函数
print("__iter__" in dir(str))
print("__iter__" in dir(dict))
print("__iter__" in dir(set))
print("__iter__" in dir(list))
print("__iter__" in dir(tuple))
print("__iter__" in dir(enumerate))
print("__iter__" in dir(range)) 运行结果:
False
False
True
True
True
True
True
True
True
6,那我们看一下者个__iter__是个什么鬼?结论:他们都是iterator,所有这些数据,执行了__iter__之后返回的都是一个iterator,就是迭代器
print([])
print([].__iter__())
print(list.__iter__([]))
print({}.__iter__())
print({1:2}.__iter__())
print(range(3).__iter__())
print(''.__iter__())
print(enumerate([]).__iter__())
print((1,).__iter__()) 运行结果:
[]
<list_iterator object at 0x10b127630>
<list_iterator object at 0x10b127630>
<dict_keyiterator object at 0x10b0d8e08>
<dict_keyiterator object at 0x10b0d8e08>
<range_iterator object at 0x10b16c4e0>
<str_iterator object at 0x10b0f77b8>
<enumerate object at 0x10b200990>
<tuple_iterator object at 0x10b127630>
7,看看迭代器独有的函数有哪些? 他们有一个共同的函数就是__next__
# 那我们看看迭代器比原来的数据多了哪些函数?求差集
print(set(dir([].__iter__()))-set(dir([])))
print(set(dir({}.__iter__()))-set(dir({})))
print(set(dir(''.__iter__()))-set(dir('')))
print(set(dir(range(10).__iter__()))-set(dir(range(10))))
# lengh_hint 元素个数
运行结果:
{'__length_hint__', '__next__', '__setstate__'}
{'__length_hint__', '__next__'}
{'__length_hint__', '__next__', '__setstate__'}
{'__length_hint__', '__next__', '__setstate__'}
8,结论,可迭代的,只要含有__iter__方法的就是可迭代的,可迭代协议里面规定的,协议就是约定好了的
迭代器都是可迭代的,可迭代的不一定是迭代器,只要是可以for循环的就都是可迭代的,就有__iter__方法,只有可迭代的才可以用for
写成可迭代对象,就是为了用for,不确定是否可以for,判断一下是否是可迭代的。
9,迭代器,迭代器协议,从容器中一个一个取值,可以取到所有的值,节省内存空间,含有__next__方法和__iter__两个方法
迭代器并不会在内存中在占用一大块内存,而是随着循环,每次生成一个,每次next在给我一个,要一个给一个,内存中永远只有一个
而且执行速度不会慢,就算真的一次全部要过来,操作系统,找地存这些数据也是很浪费时间的,所以迭代器还是很有好处的
my_list =[1,2,3,4]
my_list_iter =my_list.__iter__() ret = '__iter__' in dir(my_list_iter)
print(ret)
ret = '__next__' in dir(my_list_iter)
print(ret) ret = '__iter__' in dir(my_list)
print(ret)
ret = '__next__' in dir(my_list)
print(ret) 运行结果:
True
True
True
False
10,range ,文件句柄都是可迭代的,range可以切片的
print(range(1000)) # 这是一个可迭代对象,我给是给他要了1000个数,系统答应了,但是没有给,文件句柄也是,你打开文件时,并没有真正打文件加载到内存而是后面read的时候才去加载
print(list(range(1000))) # 这样取的话,会占用大量内存,会取出所有的数放到内存里面 # range是可以切片的 print(range(1000)[1:100])
print(list(range(1000)[1:100]))# 同样占用内存
11,迭代器循环结束会报错,因为取不到下一个值了,这个错误其实可以自己去处理的
my_list =[1,2,3,4]
my_list_iter =my_list.__iter__() # 一个列表执行了__iter__方法返回值就是一个迭代器
while True:
print(my_list_iter.__next__()) 运行结果:
1
Traceback (most recent call last):
2
File "/Users/guolixiao/PycharmProjects/lisa's_practise/boys/13.3.py", line 22, in <module>
3
print(my_list_iter.__next__())
4
StopIteration
12,如果我想写一个函数,一个一个的给我数据,而不是一次全给我,怎么办?生成器,自己写一个迭代器,其实就是生成器
我不能一直用next去调用,强制转换,会全部加载到内存,不想生产数据了,我想生产字符串,生成器函数
13,不想把所有数据一次性加载到内存,还要处处使用它,所以才有了生成器函数,因为普通的迭代器已经不能满足我们要求了,我们要自己来写
生成器有两种形式:生成器函数,本质就是我们自己写的函数,另外一个是生成器表达式
def func():
for i in range(2000000):
i = 'lisa%s'%i
return i # 这样并不能解决我的问题,因为return只可以return一次
#写到函数里面是因为我要多次使用这个函数
14,其实__iter__和__next__的字眼,我们在实际编程的时候是不会出现的,但是我们要知道原理,知道我们调用for循环的时候,内部就是这么走的,而且前面这么多也是为了后面生成器做铺垫
15,既然return不可以,那怎么?yield,生成器本质还是迭代器,就是自己写的迭代器,把普通函数的return改成yeild 就变成了生成器函数
两者共同点就是都只能在函数内部用,而且不能共用
def generator():
print(1)
yield 'a' ret = generator() # 返回值就是一个生成器
print(ret) 运行结果:
<generator object generator at 0x103845480>
16,我们会发现返回的生成器里面是有__iter__和__next__方法的,他就是一个迭代器
17,我们调用生成器的时候,并不会执行里面的代码,知道我们要用生成器里面的数据的时候才会去运行里面的代码
def generator(): # 第一步定义一个函数
print(1) #第五步执行生成器里面的代码
yield 'a' # 第六步 ret = generator() # 第二步调用函数返回给ret
print(ret) #第三步打印
print(ret.__next__()) # 第四步调用生成器里面的数值
18,多个yield,调用一次next走到一个yield,知道没有了,会抛出错误,内部函数执行会受到外部的控制
def generator():
print(1)
yield 'a'
print(2)
yield 'b' ret = generator()
print(ret)
print(ret.__next__()) 运行结果:
<generator object generator at 0x105895480>
1
a
19,如何才能不抛出错误,不能用next调用,需要用for 来调用
def generator():
yield 'a'
yield 'b'
yield 'c'
yield 'd' ret = generator()
print(ret)
for i in ret:
print(i) 运行结果:
<generator object generator at 0x105fb2480>
a
b
c
d
20,200万个Lisa字符串
def generator(): #定义生成器函数
for i in range(200000):
yield "lisa%s"%i gene_lisa = generator() for i in gene_lisa:
print(i) # 运行速度非常快,因为是要一个,给一个的,不占用内存
21,而且我们可以再取出字符串以后自己在做一些操作,比方说只要前50个,或者每个串前面加三个星号,等等
22,两个生成器是单独的,不要混了
def generator(): #定义生成器函数
for i in range(200000):
yield "lisa%s"%i gene_lisa1 = generator()
gene_lisa2 = generator() print(gene_lisa1.__next__())
print(gene_lisa2.__next__()) 运行结果:
lisa0
lisa0
23,每次for循环都是一个新的迭代器
li = [1,2,3,4]
# 列表不是一个迭代器,只是一个可迭代的,所以每次执行for循环的时候,会转化为一个迭代器,每次
# 转化出来的都是新的 for i in li:
print(i )
if i == 2:
break for i in li:
print(i)
24,实现一个监听用户输入的功能,代码和老师一模一样,但是不监听,为啥呢?
def tail(filename):
f1 = open(filename,encoding="utf-8")
# 下面我不可以用for循环,read或者readlines ,因为这些运行完了都会自动结束
# 怎么办,我们用while True,这个会一直执行,不会结束,只不过后面打印的都是空而已
while True:
line = f1.readline()
if line.strip(): #非空再打印,这样后面就不会覆盖掉了
yield line.strip() # 我想要处理一下这个数据了,那么我必须把这个数据返回回去,但是return只能返回一个,所以必须要yield g = tail("file.txt") for i in g:
print(i)
25,验证可迭代协议,和迭代器协议
from collections import Iterator # 迭代器,import就是别人写好了的
from collections import Iterable # 可迭代的 print(isinstance([],Iterable))
print(isinstance([],Iterator)) print(isinstance([].__iter__(),Iterable))
print(isinstance([].__iter__(),Iterator)) 运行结果:
True
False
True
True
26,只有next啥也不是
# 自己定义一个数据类型
class A:
def __iter__(self):pass
def __next__(self):pass # 实例化一个对象
a = A()
print(isinstance(a,Iterable))
print(isinstance(a,Iterator)) 运行结果:
True
True
27,
li = [1,2,3,4] for i in li:
print(i) for i in li.__iter__():
print(i) for i in li.__iter__().__iter__(): # 这个其实就没有意义了,前面已经是可迭代的了
print(li) 运行结果:
1
2
3
4
1
2
3
4
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
28,可迭代的.__iter__方法就可以得到一个迭代器,猜测是一个可迭代的,类似range这种,告诉你有10个数,实际上没给你,就可以用for来拿
直接告诉你是一个可迭代器,直接告诉你内存地址的
day13: 迭代器和生成器的更多相关文章
- day13迭代器与生成器
三个作业: # 1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码 login_dic = {'alex':False} def ...
- DAY13 迭代器与生成器
一.迭代器 定义:器:包含了多个值的容器 迭代:循环反馈(一次从容器中取出一个值) 迭代器:从装有多个值的容器中一次取出一个值给外界 优点:不依赖索引,完成取值 缺点:不能计算长度,不能指定位取值(只 ...
- python学习 day13 迭代器,生成器,枚举对象
一.复习 1.闭包:定义在函数内部的函数(被函数嵌套的函数) 2.装饰器:闭包的一个应用场景 -- 为一个函数添加新功能的工具 3.开放封闭原则:不能修改源代码,不能修改调用方式,但可以对外提供增加新 ...
- python 全栈开发,Day13(迭代器,生成器)
一.迭代器 python 一切皆对象 能被for循环的对象就是可迭代对象 可迭代对象: str,list,tuple,dict,set,range 迭代器: f1文件句柄 dir打印该对象的所有操作方 ...
- 迭代器、生成器 day13
一 迭代器 迭代器的由来pythone2.2引进的,是一种序列(也是一种数据类型),也是为类对象提供一个序列的入口. for 循环str list tuple dict set 文件句柄可迭代: s ...
- day13 python学习 迭代器,生成器
1.可迭代:当我们打印 print(dir([1,2])) 在出现的结果中可以看到包含 '__iter__', 这个方法,#次协议叫做可迭代协议 包含'__iter__'方法的函数就是可迭代函数 ...
- Python_迭代器、生成器、列表推导式,生成器表达式
1.迭代器 (1)可迭代对象 s1 = ' for i in s1: print(i) 可迭代对象 示例结果: D:\Python36\python.exe "E:/Python/课堂视频/ ...
- Python 从零学起(纯基础) 笔记 之 迭代器、生成器和修饰器
Python的迭代器. 生成器和修饰器 1. 迭代器是访问集合元素的一种方式,从第一个到最后,只许前进不许后退. 优点:不要求事先准备好整个迭代过程中的所有元素,仅仅在迭代到某个元素时才计算该元素,而 ...
- Python之模块,迭代器与生成器
本节涉及内容: 1. 迭代器和生成器 2. 递归 3. 字符串格式化 4. 模块 内置模块 自定义模块 第三方模块 5. 序列化的模块 json pickle (一). 迭代器和生成器: 迭代器: ...
随机推荐
- IntelliJ IDEA的配置优化
IntelliJ IDEA的配置优化 我们安装完IntelliJ IDEA之后,在弹出的欢迎页面下方点击Configure,选择Setting,打开以下界面,我们在这个界面中进行配置. Appeara ...
- SNF快速开发平台MVC-名片管理(实际名片样式)
名片管理实际的做的意义在于演示应用,在这里使用的技术有排序控件,查询条件.自由样式瀑布流式分页等技术. 下面是自由样式效果图: 下面表格样式效果图: 具体操作: 新增名片 在新增时可以上传图像进行裁剪 ...
- 转移 Visual Studio 2017 的安装临时文件
每次更新 Visual Studio 2017 会在 C 盘留下大量的缓存文件,因为目录比较深,怕以后忘了,用目录链接的形式转移到其它磁盘,也好方便清理: mklink /D C:\ProgramDa ...
- 第一部分:开发前的准备-第三章 Application 基本原理
第3章 应用程序基本原理 首先我们需要强调一下Android 应用程序是用java写的.Android SDK工具编译代码并把资源文件和数据打包成一个文件.这个名字的扩展名是.APK.要在androi ...
- AllPay(欧付宝)支付接口集成
AllPay,http://www.allpay.com.tw/,欧付宝是台湾知名的第三方支付公司,拥有丰富的支付模式(支持和支付宝.财付通),只需要一次对接,各种支付模式均可使用. 接口编写SDK: ...
- 第四百节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5安装python3.5.1
第四百节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5安装python3.5.1 1.检查系统是否安装了python [root@192 ~]# rpm -qa ...
- MySQL5.7.19 服务挂掉 自动关闭 mysqld got exception 0xc000001d win 2008R2
在mysql 官网看到mysqld got exception 0xc000001dThis error message occurs because you are also using a CPU ...
- C# 窗口和程序的退出
Application.Exit(); // 通知所有消息泵必须终止,并且在处理了消息以后关闭所有应用程序窗口. // 由 .NET Compact Framework 支持. Form.Close( ...
- ABBYY OCR技术教电脑阅读缅甸语(上)
缅甸联邦共和国,原名缅甸,是东南亚的一个国家,从1962年到2010年,缅甸一直被政变后上台的军政府统治,直至最近5年它才对外界开放,与其他国家建立了贸易与文化联系. 缅甸语由很多方言组成,但所有方言 ...
- rem布局在react中的应用
摘要: 前面给大家分享了一个react项目(http://www.cnblogs.com/xiyangbaixue/p/4751904.html),这次对这个项目做了一些改进,增加了rem布局和对is ...