8列表解析_生成器表达式

 

奉节网站建设公司创新互联建站,奉节网站设计制作,有大型网站制作公司丰富经验。已为奉节上1000家提供企业网站建设服务。企业网站搭建\成都外贸网站制作要多少钱,请找那个售后服务好的奉节做网站的公司定做!

list comprehension,列表解析:

语法:

[返回值 for 元素 in 可迭代对象 if 条件]

 

注:

列表解析没有elif,如果有多个条件可用多个if或配合or或and使用;

 

列表解析是语法糖:

编译器会优化,不会因为简写而影响效率,反而因优化提高了效率,不仅字节码更少,而且减少了栈针;

减少程序员工作量,减少出错;

简化了代码,可读性增强;

 

例:

生成一个列表,元素0-9,对每一个元素自增1后求平方,返回新列表;

[(i+1)**2 for i in range(0,10)]

 

例:

获取10以内的偶数,比较执行效率;

方一:

[i for i in range(0,10) if i % 2 == 0]

方二:

even = []

for i in range(10):

    if not i % 2:   #常用not这种写法,同if i % 2 == 0:

        even.append(i)

print(even)

 

例:

[0 for _ in range(10)]

[[0] for _ in range(10)]

 

习题:

1、有这样的赋值语句:newlist=[print(i) for i in range(10)],newlist的元素打印出的是什么?

In [3]: newlist=[print(i) for i in range(5)]

0

1

2

3

4

In [4]: newlist

Out[4]: [None, None, None, None, None]   #print(i)是表达式的结果或函数计算的结果,print(i)输出到屏幕了,该列表解析没有返回值,即最后生成指定个数的None

 

2、获取20以内的偶数?如果是3的倍数也打印?

In [6]: [i for i in range(20) if not i%2]

Out[6]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

In [7]: [i for i in range(20) if not i%2 or not i%3]   #list comprehension没有elif,多个条件用多个if或配合or,and使用

Out[7]: [0, 2, 3, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18]

 

3、获取20以内既能被2整除又能被3整除的数?

方一:

In [7]: [i for i in range(20) if not i%2 and not i%3]

Out[7]: [0, 6, 12, 18]

方二:

In [8]: [i for i in range(20) if not i%2 if not i%3]

Out[8]: [0, 6, 12, 18]

 

列表解析进阶:

[expr for item in iterable if cond1 if cond2]

等价于

ret=[]

for item in iterable:

         if cond1:

                   if cond2:

                            ret.append(expr)

 

[expr for i in iterable1 for j in iterable2]

等价于

ret=[]

for i in iterable1:

         for j in iterable2:

                   ret.append(expr)

 

例:

In [10]: [(i,j) for i in 'abc' for j in range(3)]

Out[10]:

[('a', 0),

 ('a', 1),

 ('a', 2),

 ('b', 0),

 ('b', 1),

 ('b', 2),

 ('c', 0),

 ('c', 1),

 ('c', 2)]

In [11]: [[i,j] for i in 'abc' for j in range(3)]

Out[11]:

[['a', 0],

 ['a', 1],

 ['a', 2],

 ['b', 0],

 ['b', 1],

 ['b', 2],

 ['c', 0],

 ['c', 1],

 ['c', 2]]

In [12]: [{i:j} for i in 'abc' for j in range(3)]

Out[12]:

[{'a': 0},

 {'a': 1},

 {'a': 2},

 {'b': 0},

 {'b': 1},

 {'b': 2},

 {'c': 0},

 {'c': 1},

 {'c': 2}]

 

习题:

(1)如下语句的输出?

In [17]: [(i,j) for i in range(7) for j in range(20,25) if i>4 if j>23]

Out[17]: [(5, 24), (6, 24)]

In [18]: [(i,j) for i in range(7) if i>4 for j in range(20,25) if j>23]

Out[18]: [(5, 24), (6, 24)]

In [19]: [(i,j) for i in range(7) for j in range(20,25) if i>4 and j>23]   #常用此种

Out[19]: [(5, 24), (6, 24)]

 

(2)返回1到10平方的列表?

In [20]: [i**2 for i in range(1,11)]

Out[20]: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

 

(3)lst=[1,4,9,16,2,5,10,15],生成一个新列表,要求新列表元素是lst相邻两项之和?

lst = [1,4,9,16,2,5,10,15]

[lst[i]+lst[i+1] for i in range(len(lst)-1)]

 

(4)打印九九乘法表?

[print('{}*{}={:<3}{}'.format(j,i,i*j,'\n' if i==j else ''),end='') for i in range(1,10) for j in range(1,i+1)]

 

(5)'0001.abadicddus'是ID格式,要求ID格式以点号分割,左边是4位从1开始的整数,右边是10位随机小写英文字母,请依次生成前100个ID的列表?

方一:

import random

['{:04}.{}'.format(i,''.join([chr(random.randint(97,122)) for _ in range(10)])) for i in range(1,101)]

方二:

import random

import string

['{:04}.{}'.format(i,''.join([random.choice(string.ascii_lowercase) for _ in range(10)])) for i in range(1,101)]

方三:

import random

['{:04}.{}'.format(i,''.join([random.choice(bytes(range(97,123)).decode()) for _ in range(10)])) for i in range(1,101)]

 

注:

ascii,american standard code for information interchange,美国信息交换标准代码;

小写a-z对应ascii码的97-122;

ascii码表的0-127常用,0-9,\t,\n,\r,space对应的ascii;

chr(),将ascii码对应的数字转为字符;

0-31,127,33个控制字符,或通信专用字符;

32-126,95个字符;

32,空格;

48-57,0-9数字;

65-90,26个大写英文字母;

97-122,26个小写英文字母;

8,退格;

9,制表;

10,换行;

13,回车;

 

 

 

generator expression,生成器表达式:

语法:

(返回值 for 元素 in 可迭代对象 if 条件)

列表解析的[]换为()即可;

返回一个生成器;

 

和list comprehension区别:

generator expression是按需计算,或称惰性求值(延迟计算,python思想),需要的时候才计算值,不需要的时候给个对象(可理解为中间状态,是一种可迭代对象);

list comprehension是立即返回值;

预计算和延迟计算,都有应用场景;

 

生成器:

iterable,可迭代对象;

iterator,迭代器;

iterable不一定是iterator,iterator一定是iterable;

next(),用next()方法测试是否是iterator;

在迭代时最好用for控制,如果直接用next()要控制好边界,否则抛异常;

迭代完后,不能回头;

 

生成器总结:

延迟计算;

返回迭代器,可以迭代;

从前到后走完一遍后,不能回头;

 

列表解析总结:

立即计算;

返回的不是迭代器,返回可迭代对象列表;

从前到后走完一遍后,可重新回头迭代;

 

例:

In [1]: [i for i in range(5)]

Out[1]: [0, 1, 2, 3, 4]

In [2]: (i for i in range(5))

Out[2]: at 0x7fc6440cc9e8>

In [3]: for x in (i for i in range(5)):

   ...:     print(x)

   ...:    

0

1

2

3

4

In [11]: g=('{:04}'.format(i) for i in range(1,4))

In [12]: next(g)  

Out[12]: '0001'

In [13]: next(g)

Out[13]: '0002'

In [14]: next(g)

Out[14]: '0003'

In [15]: next(g)

---------------------------------------------------------------------------

StopIteration                             Traceback (most recent call last)

in ()

----> 1 next(g)

StopIteration:

In [16]: g=('{:04}'.format(i) for i in range(1,4))   #iterator最好用for控制

In [17]: for i in g:

    ...:     print(i)

    ...:    

0001

0002

0003

In [23]: lc=['{:04}'.format(i) for i in range(5)]

In [25]: for x in lc:

    ...:     print(x)

    ...: print('############')

    ...: for x in lc:

    ...:     print(x)

    ...:    

0000

0001

0002

0003

0004

############

0000

0001

0002

0003

0004

 

 

习题:

it=(print('{}'.format(i+1)) for i in range(2))

first=next(it)

second=next(it)

val=first+second

val的值是什么?   #报错,print()语句是输出到控制台,该生成器返回值为None

val=first+second语句之后,能否再次next(it)?   #不能

In [18]: it=(print('{}'.format(i+1)) for i in range(2))

In [19]: type(it)

Out[19]: generator

In [20]: first=next(it)

1

In [21]: second=next(it)

2

In [22]: val=first+second

---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

in ()

----> 1 val=first+second

TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'

 

生成器表达式和列表解析式的对比:

计算方式,生成器表达式延迟计算,列表解析式立即计算;

内存占用,单从返回值本身来说,生成器表达式省内存,列表解析式返回新的列表(构造出新的列表,需占用内存);生成器没有数据,内存占用极少,但使用时,虽然一个个返回数据,但合起来占用的内存也差不多;

计算速度,单从计算时间看,生成器表达式耗时非常短,列表解析式耗时时间长;但是生成器本身并没有返回任何值,只返回了一个生成器对象;列表解析式构造并返回了一个新的列表;

 8列表解析_生成器表达式

 

集合解析式:

语法:

{返回值 for 元素 in 可迭代对象 if 条件}

{}

立即返回一个集合;

 

例:

In [26]: {(x,x+1) for x in range(5)}

Out[26]: {(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)}

In [27]: {[x] for x in range(5)}

---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

in ()

----> 1 {[x] for x in range(5)}

in (.0)

----> 1 {[x] for x in range(5)}

TypeError: unhashable type: 'list'

 

字典解析式:

语法:

{返回值 for 元素 in 可迭代对象 if 条件}

{},用key:value形式;

立即返回一个字典;

 

例:

In [28]: {x:(x,x+1) for x in range(5)}

Out[28]: {0: (0, 1), 1: (1, 2), 2: (2, 3), 3: (3, 4), 4: (4, 5)}

In [29]: {x:[x,x+1] for x in range(5)}

Out[29]: {0: [0, 1], 1: [1, 2], 2: [2, 3], 3: [3, 4], 4: [4, 5]}

In [30]: {[x]:[x,x+1] for x in range(5)}

---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

in ()

----> 1 {[x]:[x,x+1] for x in range(5)}

in (.0)

----> 1 {[x]:[x,x+1] for x in range(5)}

TypeError: unhashable type: 'list'

In [31]: {(x,):[x,x+1] for x in range(5)}

Out[31]: {(0,): [0, 1], (1,): [1, 2], (2,): [2, 3], (3,): [3, 4], (4,): [4, 5]}

In [32]: {chr(0x41+x):x**2 for x in range(5)}

Out[32]: {'A': 0, 'B': 1, 'C': 4, 'D': 9, 'E': 16}

In [33]: {str(x):y for x in range(3) for y in range(4)}   #等价于如下

Out[33]: {'0': 3, '1': 3, '2': 3}

In [34]: ret={}

In [36]: for i in range(3):

    ...:     for j in range(4):

    ...:         ret[str(i)]=j

    ...:        

    ...:        

In [37]: ret

Out[37]: {'0': 3, '1': 3, '2': 3}

 

python2引入列表解析式;

python3引入生成器表达式;

python3引入集合解析式、字典解析式、并迁移到了2.7;

一般来说,要多应用解析式、简短、高效;

如果一个解析式非常复杂,难以读懂,要考虑拆解成for循环;

生成器和迭代器是不同的对象,但都是可迭代对象;

 

iter(iterable),将一个可迭代对象封装成一个迭代器;

next(iterator),取元素,对一个迭代器取下一个元素,如果元素全部取完,再next()会抛StopIteration异常;

 

可迭代对象:

能够通过迭代一次次返回不同元素的对象,所谓相同不是指值是否相同,而是元素在容器中是否是同一个,如list中值可重复;

可以迭代,但是未必有序,未必可索引;

可迭代对象有,list,tuple,string,bytes,bytearray,range,set,dict,iterator等;

可用成员运算符in,not in,in本质上就是在遍历对象;

 

迭代器:

特殊的对象,一定是可迭代对象,具备可迭代对象的特征;

通过iter(iterable)把一个可迭代对象封装成迭代器;

通过next()迭代迭代器对象;

生成器对象,就是迭代器对象;

迭代器不一定是生成器;

 

 

 


分享名称:8列表解析_生成器表达式
本文链接:http://pwwzsj.com/article/ggppci.html