本系列文章回顾了python大部分关键的知识点,关注那些容易被忽略的知识点。适用于有一定python基础的python学习者。本系列文章主要参考廖雪峰的python学
本系列文章回顾了 python大部分关键的知识点,关注那些容易被忽略的知识点。适用于有一定python基础的python学习者。 本系列文章主要参考廖雪峰的python学习网站。该学习网站内容全面,通俗易懂,强烈推荐初学者在这个网站学习python。
全系列 (一)python基础 (二)函数 (三)高级特性 (四)函数式编程 (五)面向对象编程
高级特性 迭代 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)。如:
>> > for ch in 'ABC' : . . . print ( ch) . . . A B C
如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断:
>> > from collections import Iterable>> > isinstance ( 'abc' , Iterable) True >> > isinstance ( [ 1 , 2 , 3 ] , Iterable) True >> > isinstance ( 123 , Iterable) False
列表生成式 列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。
>> > [ x * x for x in range ( 1 , 11 ) ] [ 1 , 4 , 9 , 16 , 25 , 36 , 49 , 64 , 81 , 100 ] >> > [ m + n for m in 'ABC' for n in 'XYZ' ] [ 'AX' , 'AY' , 'AZ' , 'BX' , 'BY' , 'BZ' , 'CX' , 'CY' , 'CZ' ]
列表生成式+if…else 不能在for循环后面加else,在for循环前面加if必须加上else
>> > [ x if x % 2 == 0 for x in range ( 1 , 11 ) ] File "" , line 1 [ x if x % 2 == 0 for x in range ( 1 , 11 ) ] ^ SyntaxError: invalid syntax>> > [ x if x % 2 == 0 else - x for x in range ( 1 , 11 ) ] [ - 1 , 2 , - 3 , 4 , - 5 , 6 , - 7 , 8 , - 9 , 10 ]
在一个列表生成式中,for前面的if … else是表达式,而for后面的if是过滤条件,不能带else。
生成器 列表生成式的缺点是会受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,会占用很大的存储空间,存储效率大大降低。 在Python中,生成器(generator)是一种一边循环一边计算的机制,可以在循环的过程中不断推算出后续的元素,因此不必创建完整的list,从而节省大量空间。
创建生成器的方法 >> > L &#61; [ x * x for x in range ( 10 ) ] >> > L[ 0 , 1 , 4 , 9 , 16 , 25 , 36 , 49 , 64 , 81 ] >> > g &#61; ( x * x for x in range ( 10 ) ) >> > g< generator object < genexpr> at 0x1022ef630 > >> > next ( g) 0 >> > next ( g) 1 >> > next ( g) 4 >> > next ( g) . . . >> > next ( g) Traceback ( most recent call last) : File "" , line 1 , in < module> StopIteration>> > g &#61; ( x * x for x in range ( 10 ) ) >> > for n in g: . . . print ( n)
def fib ( max ) : n, a, b &#61; 0 , 0 , 1 while n < max : print ( b) a, b &#61; b, a &#43; bn &#61; n &#43; 1 return &#39;done&#39;
上面的函数和generator仅一步之遥。要把fib函数变成generator&#xff0c;只需要把print(b)改为yield b就可以了&#xff1a;
def fib ( max ) : n, a, b &#61; 0 , 0 , 1 while n < max : yield ba, b &#61; b, a &#43; bn &#61; n &#43; 1 return &#39;done&#39;
generator和函数的执行流程不一样。函数是顺序执行&#xff0c;遇到return语句或者最后一行函数语句就返回。而变成generator的函数&#xff0c;在每次调用next()的时候执行&#xff0c;遇到yield语句返回&#xff0c;再次执行时从上次返回的yield语句处继续执行。举例&#xff1a;
def odd ( ) : print ( &#39;step 1&#39; ) yield 1 print ( &#39;step 2&#39; ) yield ( 3 ) print ( &#39;step 3&#39; ) yield ( 5 ) >> > o &#61; odd( ) >> > next ( o) step 1 1 >> > next ( o) step 2 3 >> > next ( o) step 3 5 >> > next ( o) Traceback ( most recent call last) : File "" , line 1 , in < module> StopIteration
用for循环调用generator时&#xff0c;发现拿不到generator的return语句的返回值。如果想要拿到返回值&#xff0c;必须捕获StopIteration错误&#xff0c;返回值包含在StopIteration的value中&#xff1a;
>> > g &#61; fib( 6 ) >> > while True : . . . try : . . . x &#61; next ( g) . . . print ( &#39;g:&#39; , x) . . . except StopIteration as e: . . . print ( &#39;Generator return value:&#39; , e. value) . . . break . . . g: 1 g: 1 g: 2 g: 3 g: 5 g: 8 Generator return value: done
迭代器 可以直接作用于for循环的对象统称为可迭代对象&#xff1a;Iterable。 可以使用isinstance()判断一个对象是否是Iterable对象。
>> > from collections. abc import Iterable>> > isinstance ( [ ] , Iterable) True >> > isinstance ( { } , Iterable) True >> > isinstance ( &#39;abc&#39; , Iterable) True >> > isinstance ( ( x for x in range ( 10 ) ) , Iterable) True >> > isinstance ( 100 , Iterable) False
可以被next()函数调用并不断返回下一个值的对象称为迭代器&#xff1a;Iterator。 可以使用isinstance()判断一个对象是否是Iterator对象。
总结&#xff1a;
凡是可作用于for循环的对象都是Iterable类型&#xff1b; 凡是可作用于next()函数的对象都是Iterator类型&#xff0c;它们表示一个惰性计算的序列&#xff1b; 集合数据类型如list、dict、str等是Iterable但不是Iterator&#xff0c;不过可以通过iter()函数获得一个Iterator对象。 更多关于迭代对象和迭代器的知识见&#xff1a;https://www.jianshu.com/p/d917b37030ef https://www.jb51.net/article/190712.htm 补充 可迭代对象和迭代器的本质&#xff1a;
可迭代对象通过__iter__方法向我们提供一个迭代器&#xff0c;我们在迭代一个可迭代对象的时候&#xff0c;实际上就是先获取该对象提供的一个迭代器&#xff0c;然后通过这个迭代器来依次获取对象中的每一个数据. 一个具备了__iter__方法的对象&#xff0c;就是一个可迭代对象。 list、tuple等都是可迭代对象&#xff0c;我们可以通过iter()函数获取这些可迭代对象的迭代器。iter()函数实际上就是调用了可迭代对象的__iter__方法。 迭代器是用来帮助我们记录每次迭代访问到的位置&#xff0c;当我们对迭代器使用next()函数的时候&#xff0c;迭代器会向我们返回它所记录位置的下一个位置的数据。 python要求迭代器本身也是可迭代的&#xff0c;所以我们还要为迭代器实现__iter__方法&#xff0c;而__iter__方法要返回一个迭代器&#xff0c;迭代器自身正是一个迭代器&#xff0c;所以迭代器的__iter__方法返回自身即可。 一个实现了__iter__方法和next()方法的对象&#xff0c;就是迭代器。 除了Python内置的iter之外&#xff0c;还可以通过Python内置的工具包itertools创建迭代器。 for…in…循环本质 for item in Iterable循环的本质就是先通过iter()函数获取可迭代对象Iterable的迭代器&#xff0c;然后对获取到的迭代器不断调用next()方法来获取下一个值并将其赋值给item&#xff0c;当遇到StopIteration的异常后循环结束。
生成器和yield 生成器一定是迭代器&#xff0c;但是迭代器不全是生成器对象。 生成器的的特点是运行速度块&#xff0c;最大优点是节省内存。 包含yield关键字的函数将是一个生成器对象。 这个生成器有一个函数就是next函数&#xff0c;next就相当于“下一步”生成哪个数&#xff0c;这一次的next开始的地方是接着上一次的next停止的地方执行的&#xff0c;所以调用next的时候&#xff0c;生成器并不会从foo函数的开始执行&#xff0c;只是接着上一步停止的地方开始&#xff0c;然后遇到yield后&#xff0c;return出要生成的数&#xff0c;此步就结束。 除了yield之外&#xff0c;在Python3.3之后还加入了yield from获取生成器&#xff0c;允许一个生成器将其部分操作委派给另一个生成器&#xff0c;yield from后面需要加上可迭代对象&#xff0c;这样可以把可迭代对象变成生成器。 python3的range()就是xrange(),便是一个生成器。 yield的另外用法包括协程、定义上下文管理器。 参考链接&#xff1a; Python 的关键字 yield 有哪些用法和用途&#xff1f; python中yield的用法详解——最简单&#xff0c;最清晰的解释