1、可迭代对象
首先思考一个问题,什么类型是可以for循环的。
你会说有list,tuput,str,dict,set等等。他们有一个共性,就是都含有__iter__方法。
说明他们都是可迭代的对象,有兴趣的可以在pycharm打断点,看一下for循环内部是如何实现的。
也就是说:含有__iter__方法的对象都是可迭代对象。
另:只有可迭代对象才可以for循环。
2、迭代器
再次思考一个问题,假如有一个列表,有很多数据,比如占用了4g,那我们在循环的时候会不会很占空间?我电脑内存一共就那莫大,还不说系统占用的内存。在可迭代对象中我们提到了for循环内部实际上也使用了迭代器,使用迭代器可以使在循环时不占用过多的内存,这就是迭代器的神秘之处。
概念:在可迭代对象的基础上再含有__next__方法。也就是同时含有__iter__和__next__方法。
反过来想,迭代器一定是可迭代对象。但可迭代对象不一定是迭代器。
3、生成器
看过我python爬虫教程的一定看到过生成器。可能看到的时候不知道他是生成器。
为什么学习生成器?
我们目前的返回值较少,当我们返回的内容较多时,我们使用生成器返回,以此来节省内存。
3.1、生成器函数
一个简单的生成器函数
def zhangsan():
print("我是张三")
yield "张三"
print("我是李四")
yield "李四"
ret = zhangsan()
print(ret)
print(__item__ in dir(ret))
ret1 = ret.__next__()
print(ret1)
ret2 = ret.__next__()
print(ret2)
定义:当一个函数中有yield时,我们就称它为生成器函数。
yield:和return有一个共性就是也可以返回一个值(张三),不同的是,他并不代表一个函数的结束,为什么叫生成器函数?因为yield返回的是一个生成器。并且yield不能和return一起用。
结果:
ret = zhangsan() ----> <generator object zhangsan at 0x02A6FEA0>
print(__item__ in dir(ret)) ----> True
print(ret1) ----> 我是张三
----> 张三
print(ret2) ----> 我是李四
----> 李四
ret:返回的是一个生成器,并不会像ruturn那样接收到返回值
print(ret1) ret1调用一次__next__()只会取到第一个返回值和执行第一个yield上的函数体。
print(ret2) ret2算第二次调用__next__(),会从上面的yield往下执行,以下以此类推。
另:其实我们没有必要调用__next__()方法来取值,直接for循环就可以了,我们自己调用__next__()方法,当超过了返回值的数量是会报错的。(我们还没有学到报错的解决方法)
修改成:
def zhangsan():
print("我是张三")
yield "张三"
print("我是李四")
yield "李四"
ret = zhangsan()
for i in ret:
print(i)
即可。
生成器的取值特点:生成器取值是要一次循环完的,比如一个生成器有100个值,我先取了50个值,那么我们再次取值的时候是接着上次的取值也就是从第51个开始取值。
3.2、send()
def zhangsan():
print("我是张三")
name = yield "张三"
print("name:",name)
print("我是李四")
yield "李四"
ret = zhangsan()
print(ret.__next__())
print(ret.send("123"))
结果:
我是张三
张三
name: 123
我是李四
李四
可以看出我们利用send(),在第二次取值的时候将yield "张三" 替换成了123
另:第一次必须使用__next__()调用,因为还没有赋值就已经返回了。那最后一个因为他的后面没有yield了,和__next__一样,也是会报错,所以也不能接收值。
3.3、yield from(python3版本)
def zhangsan():
a = "11"
b = "22"
c = "33"
yield from a
yield from b
yield from c
yield from :集体一个一个返回,不用再内部使用for循环一个一个返回。
3.4生成器表达式
ret = (i for i in range(100))
print(ret)
输出:<generator object <genexpr> at 0x03784D50>
说明是一个装饰器。简单,但是也只能实现一些小功能。
另(列表生成式):列表也可以这样写:list = [i for i in range(100)],生成一个0到99的list。
网友评论