首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

十六、Python的语句与语法-迭代器和解析(1)

一、迭代器

1、初探

之前章节中,我们看到for语句可以Python任何序列类型,包括列表、元祖以及字符串。如下所示:

>>>foriin[1,2,3]:print(i,end=' ')...

123

>>>foriin(1,2,3):print(i,end=' ')...

123

>>>foriin'123':print(i,end=' ')...

123

下面我们继续看文件迭代器、手动迭代(iter, next)、其它内置类型迭代器。

2、文件迭代器

回忆一下之前章节,文件访问方式有如下:

.read(): 一次性读取全部内容。

.readline(): 一次读取一行。

.readlines(): 生成列表,每一行是每个元素。

.next(): 跟readline()差不多,但读取完之后报错。

next()报错,为StopIteration。在Python中任何这类对象都认为是可迭代的。在Python里迭代工具(比如for)会调用next()来获取数据,并以StopIteration来确认何时离开。

forlineinopen(): print(line, end ='')

因为每个元素在最后包涵\n(换行符),因此print函数结尾需要取消结尾中的换行。

注: 尽量不要使用readlines()函数,因为这个会一次性的把所有内容读取到内存里(转换为列表),运行速度会比较慢。最好使用readline或者迭代文件方法。

3、手动迭代

为了支持手动迭代代码,Python支持next()函数,它会自动读取next()函数。next(X)等同于X.next()。

f = open() next(f)

这个会从第一行开始读取内容。

从技术角度来讲,迭代协议里,当使用for函数进行迭代时,会传递给iter内置函数,以便可迭代对象中获取迭代器。返回的对象有需要有next()方法。

>>>L = [1,2,3]

>>>i = iter(L)

>>>next(i)

1

>>>next(i)

2

>>>next(i)

3

>>>next(i)Traceback (most recent call last): File"", line1,inStopIteration

对于文件来说,不需要转换成iter类型的这一步:

>>>file = open(r'C:\Test\test.txt')

>>>fileisiter(file)

True

因为文件对象就是自己的迭代器,但列表,元祖,字符串等就不是了。

>>>str ='123'; list = [1,2,3] ; tuple = (1,2,3)

>>>strisiter(str)

False

>>>listisiter(list)

False

>>>tupleisiter(tuple)

False

4、其他内置类型迭代器

除了文件以及像列表这样的实际的序列外,其它类型也有其适用的迭代器。例如,遍历字典键的经典方法是明确地获取其键的列表。

>>>dict = {'a':1,'b':2,'c':3}

>>>forkeyindict.keys() :

...print(key,dict[key])...a1

b2

c3

二、列表解析

1、初探

遍历列表时,使用for循环来修饰它:

>>>list = [1,2,3]

>>>foriinrange(len(list)) :

...list[i] +=10

...

>>>list[11,12,13]

这个是有效的,但不是“最佳实践”。我们可以使用产生所需结果列表的一个单个表达式来完成上面循环:

>>>list = [1,2,3]

>>>list = [i +10foriinlist]

>>>list[11,12,13]

2、列表解析基础知识

从之前的例子开始分析:list1 = [i + 10 for i in list1]

这个先是运算 [i + 10 for i in list1]之后,再把此赋值给list1。我们来看里面是如何运算:

先是对list1进行迭代,每次把单个值符给i,再进行i + 10,成为新列表的单个元素。这个相当于:

tmp = []

foriinlist1:tmp.append(i+10)list1 = tmp

可以认为是倒过来的for循环语句。

3、在文件上使用列表解析

>>>file = open(r'C:\Test\test.txt').readlines()

>>>file['DoraEmon\n','Daxiong\n','JingXiang']

在这里发现,每行最后都会有\n换行符,这个时候我们可以使用列表解析来进行去除换行符的操作。

>>>file = [line.strip()forlineinfile]

>>>file['DoraEmon','Daxiong','JingXiang']

或更简单

>>>file = [line.strip()forlineinopen(r'C:\Test\test.txt')]

还可以进行更多操作:

>>>file = [line.strip().upper()forlineinopen(r'C:\Test\test.txt')]

>>>file['DORAEMON','DAXIONG','JINGXIANG']

4、扩展的列表解析语法

扩展语法是在循环基础上,添加了条件:

>>>file = [line.strip().upper()forlineinopen(r'C:\Test\test.txt')ifline[] !='J']

>>>file['DORAEMON','DAXIONG']

在这里,发现添加 if line[0] != J’的时候,不显示以 “ J “ 开头的行。

>>>[x+yforxin[1,2,3]foryin[10,20,30]][11,21,31,12,22,32,13,23,33]

我们会发现第二个for循环算是嵌套在第一个for循环。

三、其他迭代环境

map也可用在迭代中:

>>>list(map(str.upper, open(r'C:\Test\test.txt')))['DORAEMON\n','DAXIONG\n','JINGXIANG']

map函数是把后面的可迭代的每个值当作前面的参数传入。在Python3开始正式引入map,之前版本,python2.7也可以使用,但map可以直接返回列表,不需要使用list函数进行转换。后续章节中会继续讲解。上面的可以如下解释:

>>>tmp = []

>>>forlineinopen(r'C:\Test\test.txt'):

...tmp.append(str.upper(line))...

>>>tmp['DORAEMON\n','DAXIONG\n','JINGXIANG']

相应的,也有sorted,会对迭代对象进行排序后生成列表。

>>>sorted(open(r'C:\Test\test.txt'))['Daxiong\n','DoraEmon\n','JingXiang']

enumerate也会对迭代对象进行运算后,生成可迭代对象。

>>>list(enumerate(open(r'C:\Test\test.txt')))[(,'DoraEmon\n'), (1,'Daxiong\n'), (2,'JingXiang')]

enumerate就是在原有的顺序中添加序列号。除了这些,还有filter与reduce方法,这些再后续章节讲解用法。

>>>list(filter(bool,open(r'C:\Test\test.txt')))['DoraEmon\n','Daxiong\n','JingXiang']

>>>importoperator,functools

>>>functools.reduce(operator.add,open(r'C:\Test\test.txt'))

'DoraEmon\nDaxiong\nJingXiang'

sum、any、all、max、min也可使用迭代器。

any() 函数用于判断给定的可迭代参数 iterable 是否全部为 False,则返回 False,如果有一个为 True,则返回 True。元素除了是 0、空、FALSE 外都算 TRUE。

all() 函数用于判断给定的可迭代参数 iterable 中的所有元素是否都为 TRUE,如果是返回 True,否则返回 False。元素除了是 0、空、None、False 外都算 True。

>>>sum((1,2,3)),sum([4,5,6])(6,15)

>>>any([1,[],'True']), all([1,[],'True'])(True,False)

>>>max([2,3,1]),min([2,3,1])(3,1)

list, tuple, join 都是可以对可迭代对象进行操作后输出:

>>>list(open(r'C:\Test\test.txt')),tuple(open(r'C:\Test\test.txt')),'**'.join(open(r'C:\Test\test.txt'))(['DoraEmon\n','Daxiong\n','JingXiang'], ('DoraEmon\n','Daxiong\n','JingXiang'),'DoraEmon\n**Daxiong\n**JingXiang')

四、Python3中新的迭代环境

从Python3.x开始,更注重迭代。在Python2.x里,很多函数生成的是列表方式:

>>>zip('abc','123')[('a','1'), ('b','2'), ('c','3')]

但在Python3.x开始是变成可迭代的特定对象:

Python 3.x的这种方式,会延迟计算,在提取内容的时候计算结果。这样会节省内存空间,不需要提前计算后放进内存里。迭代对象,当迭代完成之后,不能再次读取。

>>>a = list(zip('abc','123'))

>>>foriina: print(i, end=' ')...('a','1') ('b','2') ('c','3') >>>

>>>foriina: print(i, end=' ')...>>>

1、range

range从Python3.x开始变为迭代器。

Python 2.x:

>>>range(5)[,1,2,3,4]

Python 3.x:

>>>range(5)range(,5)

所以,在Python 3.x要是需要生成一个有序列表,需要再次转换:

>>>list(range(5))[,1,2,3,4]

但也可以像列表一样使用:

>>>range(5)[1]

1

>>>range(5)[-1]

4

注:range可继续使用。

>>>r = range(7)

>>>foriinr :

...print(i,end =' ')...

123456>>>

>>>foriinr :

...print(i,end =' ')...

123456>>>

2、map、zip和filter

在Python3.x里,map、zip和filter也是使用迭代器来节约内存开销。但与range不同,使用一次之后,就不能再次使用。

>>>M = map(abs,(-1,3,7))

>>>list(M)[1,3,7]

>>>list(M)[]

>>>Z = zip((1,2,3),('a','b','c'))

>>>list(Z)[(1,'a'), (2,'b'), (3,'c')]

>>>list(Z)[]

>>>F = filter(bool,(1,'','True'))

>>>list(F)[1,'True']

>>>list(F)[]

map() 函数会根据提供的函数对指定序列做映射。第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。

zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。我们可以使用 list() 转换来输出列表。如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。

filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换。该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。

五、多个迭代器 vs 单个迭代器

之前看到的range,可以同时使用多个迭代器。这个叫range有着多个迭代器。可以进行索引。但其它的,只能迭代一次。

后续章节会看到各种迭代器,而且会说明如何生成两种迭代器。

六、字典视图迭代器

字典视图迭代器,与其它多个迭代器相似(在Python2.x里还是使用列表)

>>>dict = {'a':1,'b':2,'C':3}

>>>dict.keys()dict_keys(['a','b','C'])

>>>dict.values()dict_values([1,2,3])

>>>dict.items()dict_items([('a',1), ('b',2), ('C',3)])

在这里,迭代器都算是多个迭代器(Python3.4为基准)

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190203B0MJW500?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券