摘要:开始本文主要记录廖大教程中高级特性这一节的内容,并写下我的一些理解。廖大的教程中是这样说的函数是顺序执行,遇到语句或者最后一行函数语句就返回。
前言
用 python 差不多半年多了,从去年暑假开始接触,从开始的懵逼,到写了一些小爬虫总算入门之后,许多作业也是能用 python 就用 python,基本抛弃了 C++。但是还是有些过于急躁了,能够写一些简短的代码,但是对于 python 的很多特性都不知道或者忘记了,这里回去廖大教程复习一下,顺便记录下我觉得比较重要的地方。
开始本文主要记录廖大教程中高级特性这一节的内容,并写下我的一些理解。在我看来,这些特性是很 pythonic 的,用在代码中很有 bigger 啊~
列表生成式(List Comprehensions)切片和迭代就不说了,这里直接先看一下列表生成式吧,从名字就能大概猜出这是生成列表的一些方法,比如:如何生成[1*1, 2*2, ... ,10*10]?可以用循环不断向列表尾部添加元素,如果使用 pythonic 的方法,也就是列表生成式,则是:
>>> [x * x for x in range(1, 11)] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
后面还能跟上 if 判断,例如:
>>> [x * x for x in range(1, 11) if x%2==0] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
这样,本来需要使用循环写4,5行的代码,使用一行就解决了,直观明了。
还能使用两个 for 循环生成全排列:
>>> [m + n for m in "ABC" for n in "XYZ"] ["AX", "AY", "AZ", "BX", "BY", "BZ", "CX", "CY", "CZ"]
这样如何添加 if 判断呢?可以在每个 for 语句后添加,或者在最后添加:
>>> [m + n for m in "ABC" if m < "C" for n in "XYZ" if n < "Z"] ["AX", "AY", "BX", "BY"] >>> [m + n for m in "ABC" for n in "XYZ" if n < "Z" and m < "C"] ["AX", "AY", "BX", "BY"]
也可以同时在一个 for 语句中迭代多个变量,比如dict的items()可以同时迭代key和value:
>>> d = {"x": "A", "y": "B", "z": "C" } >>> [k + "=" + v for k, v in d.items()] ["y=B", "x=A", "z=C"]
差不多就是这样了~
但是以前总是写 C++ ,这种思维模式很难改过来,只能慢慢在使用中熟悉这种语法,习惯了就能够在下意识中写出来了。
生成器(Generator)为什么要使用生成器?廖大的教程中说得很详细,这里再简述一下:
因为列表的内容放在内存中,而受到内存限制,列表的容量有限。
如果我们只访问极少的元素,那么存在极大的空间浪费。
而生成器可以一边迭代一边计算下一个值,理论上,该过程可以无限进行下去,并且不会占用大量内存。
这里只是简单介绍一下,更详细的请 Google 哈~
如何创建生成器?第一种方法类似于前面讲到的列表生成式,只需要将[]改为()即可:
>>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range(10)) >>> gat 0x1022ef630>
可以看到,方法上大致相同,[]得到的是一个已经得到所有值的列表,()得到的是一个生成器,它们都能使用 for 循环来迭代,但是生成器不能使用下标访问,并且只能被迭代一次,再次迭代则会有 StopIteration 的异常:
>>> for i in g: ... print(i) ... 0 1 4 9 16 25 36 49 64 81 >>> for i in g: ... print(i) ... >>> next(g) Traceback (most recent call last): File "", line 1, in StopIteration
不过当我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。
如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现,比如,著名的斐波那契数列:
def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n = n + 1 return "done"
关于 yield 这个关键字,我在刚学 python 的时候也纠结了很久,直到看到生成器的时候才大致明白,大家搜索一下就能大致明白了,我觉得这东西说起来麻烦,只说一两句又怕说错。廖大的教程中是这样说的:
函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
可能有点难理解,不过明白了就很好说了。
当然,函数中还可以添加 return,在一个 generator function 中,如果没有 return,则默认执行至函数完毕,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代。
例如上面的例子,我们在迭代时发现并没有出现 "done" 这串字符,是因为 return 的值被当作 Exception Value 了,如果要显示出来,则可以这样:
>>> g = fib(6) >>> while True: ... try: ... x = next(g) ... print("g:", x) ... except StopIteration as e: ... print("Generator return value:", e.value) ... break ... g: 1 g: 1 g: 2 g: 3 g: 5 g: 8 Generator return value: done迭代器(Iterator)
可直接作用于 for 循环的对象被称为可迭代对象,可以用 isinstance() 函数判断是否为可迭代对象:
>>> from collections import Iterable >>> isinstance([], Iterable) True >>> isinstance({}, Iterable) True >>> isinstance("abc", Iterable) True >>> isinstance((x for x in range(10)), Iterable) True >>> isinstance(100, Iterable) False
而可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。当然,仍然可以使用isinstance()判断一个对象是否是Iterator对象:
>>> from collections import Iterator >>> isinstance((x for x in range(10)), Iterator) True >>> isinstance([], Iterator) False >>> isinstance({}, Iterator) False >>> isinstance("abc", Iterator) False
通过上面两个例子,可以这样理解:生成器和 list,tuple,str 等都是 Iterable 对象,生成器同时还是 Iterator 对象,而 list 等不是。那么能否直接将 Iterable 对象转换成 Iterator 对象呢?
可以使用iter()函数:
>>> isinstance(iter([]), Iterator) True >>> isinstance(iter("abc"), Iterator) True
其实,Iterator 对象表示的是一个数据流,我们可以把这个数据流看做是一个有序序列,但却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以 Iterator 的计算是惰性的,只有在需要返回下一个数据时它才会计算。Iterator甚至可以表示一个无限大的数据流,但 list,tuple 什么的是不可能这样的。
总结过了个寒假没碰代码,相当于复习了一遍啊,其实这里说到的特性是很浅显的,理解起来不难,等全部差不多复习完还得再深入一点,理解更多才行。
以上~
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/38411.html
摘要:关于作者是软件基金会的成员,也是巴西第一个黑客空间的联合创始人。他曾在巴西媒体,银行和政府部门教授开发,并在,,和上发表演讲。他是一位自学成才的程序员,也是使用学习编程一系列书的作者。 showImg(https://segmentfault.com/img/remote/1460000018926735); 来源 | 愿码(ChainDesk.CN)内容编辑 愿码Slogan | ...
摘要:但是相对于开发者来说语言提供了更加强大的支持。自身的强类型的机制异常处理垃圾自动收集等是其程序健壮性的重要保证。框架的设计理念也遵循了优雅明确简单,并具有简洁易读及可拓展性。 关于Python的发展,及Python的历史概述我这里将不会浪费时间和大家介绍,因为我觉得能够借用搜索引擎搜索到的知识大家就竟可能的自己动手动脑去了解和认知,我主要就讲讲Python的一些基本的特性及版本的选择相...
摘要:尽管如此,还具有高级的数据类型和灵活性。它配备了大量的标准模块,可用于程序库。一些模块提供如下功能通过这些很赞的特性,瞬时化身为面向过程的语言。开发者可以便捷地将解释器连接到一个使用编写的应用程序,并能随时用作扩展。下一部分会继续分享。 【编者按】本文作者是 Abhishek Jaiswal ,擅长 .NET、C#、Python 等多种语言的技术控。本文中,作者通过活泼有趣的口吻向大家...
摘要:所以如果像上述这样引入模块的时候,调用函数必须加上模块名通常情况下鼓励每个语句只导入一个包方便理解和阅读代码。 今天我们学习Python的高级特性、模块和IO操作,通过学习这些,我们可以更快的了解Python,使用Python。 高级特性中会讲述列表生成式、生成器、和一些高级函数,学习这些方便我们快速的生成列表,节省我们使用Python的时间,更快的使用Python达成我们的目的。 模...
阅读 3722·2021-10-11 10:59
阅读 1304·2019-08-30 15:44
阅读 3482·2019-08-29 16:39
阅读 2890·2019-08-29 16:29
阅读 1802·2019-08-29 15:24
阅读 810·2019-08-29 15:05
阅读 1264·2019-08-29 12:34
阅读 2306·2019-08-29 12:19