本文主要介绍Python的高级特性:列表推导、迭代器和生成器,这些都是面试中经常被问到的特性。因为生成器实现了迭代器协议,所以可以通过列表理解生成。所以这三个概念作为一个章节来介绍,最容易让大家理解。如果你现在不明白也没关系。我不仅会让你知道以下内容但是,重要的是要知道为什么。Listcomprehension前几天有个HR找我聊listcomprehension。我说我经常使用这个公式从旧列表生成新列表。他直接拒绝了我,让我回去复习。,挺受打击的,所以决定帮大家复习一下。内容:列表推导:旧列表->新列表推导:字典推导集合推导1,列表推导格式[expressionforvariableinoldlist]or[expressionforvariableinoldlistifcondition]例1:生成一个新列表,其名称length大于3且首字母大写。names_old=['tom','amy','daming','lingling']names_new=[name.capitalize()fornameinnames_oldiflen(name)>3]print(names_new)output:['Daming','玲玲']例2:(大厂小学笔试题)生成一个元组列表,要求每个元素的形式为(0-5个偶数,0-10个奇数)。输出为:[(0,1),(0,3),(0,5),(0,7),(0,9),(2,1),(2,3),(2,5),(2,7),(2,9),(4,1),(4,3),(4,5),(4,7),(4,9)]for循环实现代码:new_list=list()foriinrange(5):#偶数ifi%2==0:forjinrange(10):#奇数ifj%2!=0:new_list.append((i,j))列表理解代码:new_list=[(i,j)foriinrange(5)forjinrange(10)ifi%2==0andj%2!=0]例3:(大厂小学笔试题)给出员工名单:employees_old=[{'name':"tmo","salary":4800},{'name':"amy","salary":3800},{'name':"daming","salary":7000},{'name':"lingling","salary":5600}]如果员工工资大于5000则加200,否则加500,输出新的员工列表。列表理解:employees_new=[employee['salary']+200ifemployee['salary']>5000elseemployee['salary']+500foremployeeinemployee_old]print(employees_new)输出:[5300,4300,7200,5800】发现结果是员工工资的列表。回头看代码,确实是把获取到的数字给了列表,那么如何返回员工列表呢?让我们将其与普通的for循环进行比较:foremployeeinemployees_old:ifemployee['salary']>5000:employee['salary']+=200else:employee['salary']+=500print(employees_old)输出:[{'name':'tmo','salary':5300},{'name':'amy','salary':4300},{'name':'daming','salary':7200},{'name':'lingling','salary':5800}]没错,我们注意到了两者的区别。对于列表理解,我们少了一个赋值(字典元素上的赋值),所以我们不能直接将薪水值而不是员工字典返回到列表中。正确的列表理解如下:employees_new=[{'name':employee['name'],'salary':employee['salary']+200}ifemployee['salary']>5000else{'name':employee['name'],'salary':employee['salary']+500}foremployeeinemployees_old]print(employees_new)2.字典推导:例1:dict_old={'a':'A','b':'B','c':'C','d':'C'}dict_new={value:keyforkey,valueindict_old.items()}print(dict_new)output:{'A':'a','B':'b','C':'d'}3.集合理解:类似于列表理解典型用法:去重示例1:list_old=[1,2,3,5,2,3]set_new={xforxinlist_old}print(set_new)output:{1,2,3,5}总结:至此,列表推导不就是一个创建列表的公式吗?除了简化代码,安装X?其实列表推导还有一个好处就是比for循环更高效,因为列表推导在执行的时候调用了Python底层的C代码,而for循环是用Python代码执行的。哇~面试官最想听到的是第二点。迭代器因为迭代器协议对于很多人来说是一个比较抽象的概念,而生成器自动实现了迭代器协议,所以我们需要先解释一下迭代器协议的概念,以便更好的理解下面的Builder。能被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。迭代是一种访问集合元素的方式,而迭代器是一种记住遍历位置的对象。迭代器对象从集合的第一个元素开始访问,直到访问完所有元素。迭代器只能前进不能后退。迭代器协议:表示对象需要提供一个__next__()方法,该方法要么返回迭代中的下一项,要么引发StopIteration异常终止迭代。可迭代对象:它是一个实现了迭代器协议的对象。比如稍微熟悉Python的朋友应该都知道,Python的for循环不仅可以用来遍历列表,还可以用来遍历文件对象,如下图:withopen('F:/test/test.txt')asf:forlineinf:print(line)为什么Python中可以使用for循环遍历文件?这是因为,在Python中,文件对象实现了迭代器协议,for循环并不知道自己遍历的是一个文件对象,它只是使用迭代器协议来访问这个对象。正是因为Python的文件对象实现了迭代器协议,我们才能如此方便地访问文件,如下:withopen('F:/test/test.txt')asf:print(dir(f))输出:['__class__','__del__','__dict__','__dir__','__init__','__iter__','__next__','closed','line_buffering','newlines','read','readline'...]iterable绝对是一个迭代器吗?生成器是可迭代对象,也是迭代器。列表是可迭代对象,但不是迭代器。list可以使用iter()函数将iterable变成迭代器list->iter(list)->iteratornext():例如:list1=iter([xforxinrange(10)])print(next(list1))print(next(list1))iterableobject:generatortuplelistcollectiondictionarystring如何判断一个对象是否可迭代?在isinstance()函数的帮助下:fromcollectionsimportIterableprint(isinstance([xforxinrange(10)],Iterable))#listprint(isinstance('helloworld',Iterable))#stringprint(isinstance(100,Iterable))#Numberprint(isinstance((xforxinrange(10)),Iterable))#Iteratoroutput:TrueTrueFalseTrueGenerator生成器是Python最有用的特性之一,但也是应用最少的使用了Python的特性之一。究其原因,主要是其他主流语言没有生成器的概念。也正是因为生成器是一个“新”的东西,所以一方面没有引起广大工程师的重视,另一方面也增加了工程师的学习成本,最终导致大家错过Python中如此有用的功能。我们已经知道可以直接通过列表理解来创建列表,但是由于内存限制,列表的容量必须是有限的。而且,创建一个包含100万个元素的列表,不仅占用大量存储空间,而且如果我们只需要访问前几个元素,后面的大部分元素占用的空间都会被浪费掉。因此,如果列表元素能够在循环的过程中按照一定的算法不断计算出后面的元素,就不需要创建一个完整的列表,这样也可以节省很多空间。在Python中,这种while循环计算的机制被称为生成器:generator。Python使用生成器提供对延迟操作的支持。所谓延迟操作,就是在需要的时候才产生结果,而不是马上产生。这也是生成器的主要好处。定义生成器Python以两种不同的方式提供生成器:方法一:使用列表推导生成器表达式:类似于列表推导(这也是我在第一节介绍列表推导的原因),但是,生成返回一个按需产生结果的对象,而不是而不是一次构建一个结果列表。例1:my_generator=(xforxinrange(5))#注意()不是[]print(my_generator)#发现无法打印元素print(type(my_generator))print(my_generator.__next__())#三种获取元素的方式,注意输出print(next(my_generator))foriinmy_generator:print(i)#注意会抛出StopIteration异常#print(next(my_generator))print(next(my_generator))#生成器只能遍历输出一次:Traceback(mostrecentcalllast):File"E:/pycharm/Leetcode/RL_Learning/printdata.py",line11,in
