python基础四

无论是风里,还是在雨里,我都在这里守候着你~

可迭代对象

首先思考一个问题,什么类型是可以for循环的。你会说有list,tuput,str,dict,set等等。他们有一个共性,就是都含有__iter__方法。说明他们都是可迭代的对象,有兴趣的可以在pycharm打断点,看一下for循环内部是如何实现的。

也就是说:含有__iter__方法的对象都是可迭代对象。

另:只有可迭代对象才可以for循环。

迭代器

再次思考一个问题,假如有一个列表,有很多数据,比如占用了4g,那我们在循环的时候会不会很占空间?我电脑内存一共就那莫大,还不说系统占用的内存。在可迭代对象中我们提到了for循环内部实际上也使用了迭代器,使用迭代器可以使在循环时不占用过多的内存,这就是迭代器的神秘之处。

概念:在可迭代对象的基础上再含有__next__方法。也就是同时含有__iter__和__next__方法。

反过来想,迭代器一定是可迭代对象。但可迭代对象不一定是迭代器。

生成器

看过我python爬虫教程的一定看到过生成器。可能看到的时候不知道他是生成器。

为什么学习生成器?

我们目前的返回值较少,当我们返回的内容较多时,我们使用生成器返回,以此来节省内存。

生成器函数

一个简单的生成器函数:

实例:

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个开始取值。

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__一样,也是会报错,所以也不能接收值。

yield from(python3版本)

def zhangsan():

a = "11"

b = "22"

c = "33"

yield from a

yield from b

yield from c

yield from :集体一个一个返回,不用再内部使用for循环一个一个返回。

生成器表达式

ret = (i for i in range(100))

print(ret)

输出:<generator object <genexpr> at 0x03784D50>

说明是一个装饰器。简单,但是也只能实现一些小功能。

另(列表生成式):列表也可以这样写:list = [i for i in range(100)],生成一个0到99的list。

本文分享自微信公众号 - python入门到放弃(python_xuexi)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-09-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 组合模式就是几个模式组合一起吗?来看看组合模式原理

    在上一个《迭代器模式》中,我们讲到了阿里收购网易考拉后,店铺合并的问题使用到了迭代器模式。现在又有了新需求。我们先来看看新需求:

    凯哥Java
  • 终于还是对TA下了手!小白教学:模拟登陆网站并爬取信息

    相信很多读者多多少少都玩过模拟登陆某某网站、爬取某某网站数据等等,对于高手来说这篇文章简直是小菜一碟,不过对于入门级程序猿来说可能将会是ta跨入网络编程的第一步...

    beifengtz
  • Groovy 使一个类不可变

    创建不可变对象,创建后不能更改。 这使得不可变对象在并发和函数编程中非常有用。 要将Java类定义为不可变,我们必须将所有属性定义为readonly和priva...

    白石
  • 搜索引擎的预料库 —— 万恶的爬虫

    本节我们来生产一个简单的语料库 —— 从果壳网爬点文章。后面我们将使用这些文章来完成索引构建和关键词查询功能。

    老钱
  • 并发面试必备系列之并发基础与内存模型

    在 《Awesome Interviews》 归纳的常见面试题中,无论前后端,并发与异步的相关知识都是面试的中重中之重,本系列即对于面试中常见的并发知识再进行回...

    王下邀月熊
  • Apache Solr DataImportHandler RCE

    由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测以及文章作者不为此承担任何责任。 雷神众测拥有对此文章的修改和...

    安恒网络空间安全讲武堂
  • JS中的变量和类型计算

    值类型(boolean,string,number,null,undefined)

    ConardLi
  • Groovy 简单的`@ToString`注解

    从Groovy 1.8开始,我们可以使用@ToString注释来轻松创建toString()方法。 我们只需要在类定义中添加注释,我们就可以获得类的属性的格式良...

    白石
  • [JVM] JVM自动内存管理机制(一)

    文本主要就JVM结构和字节码文件,进行分析来展开JVM的学习,后续系列文章会从JVM的多个方面的进行知识总结。

    架构探险之道
  • 并发面试必备系列之进程、线程与协程

    在 《Awesome Interviews》 归纳的常见面试题中,无论前后端,并发与异步的相关知识都是面试的中重中之重,《并发编程》系列即对于面试中常见的并发知...

    王下邀月熊

扫码关注云+社区

领取腾讯云代金券