21列表解析、生成器表达式

1、列表解析:函数式编程工具
列表解析是最常应用迭代协议的环境之一
列表解析也不是必须的,我们也可以手动循环来完成列表解析的工作,但是,列表解析看起来更加精简,
而且,列表解析比手动for循环执行速度更快,因为它们的迭代在解释器内部是以C语言的速度执行的,而不是以手动代码执行的
特别是对于较大的数据集合,这是列表解析的一个主要性能优点

l = [1,2,3,4,5,6]
l_new = [i for i in l if i%2==0] # (for i in l)就是一个可迭代对象
l = [x+y for x in 'abc' for y in 'lmn'] #['al', 'am', 'an', 'bl', 'bm', 'bn', 'cl', 'cm', 'cn']

 2、列表解析和map

# 尽量让map调用和列表解析简单易懂
res = list(map(ord, 'spam'))
res = [ord(x) for x in 'spam'] #[115, 112, 97, 109]

res2 = [x ** 2 for x in range(10)]
res2 = list(map(lambda x: x**2, range(10))) #[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

res3 = [x for x in range(5) if x % 2 == 0]# 使用if分支的列表解析和filter()
res3 = list(filter((lambda x:x % 2 == 0), range(5)))

# 一个列表解析实现map+filter的功能
res4 = [x ** 2 for x in range(10) if x % 2 == 0]
res4 = list(map((lambda x:x**2),filter((lambda x:x%2 == 0),range(10)))) #[0, 4, 16, 36, 64]

3、字典解析、集合解析
字典解析、集合解析只是把生成器表达式传递给类型名的语法糖
字典解析、集合解析可以在任何类型的可迭代对象上迭代,支持if,for

s1 = {x*x for x in range(5)} #{0, 1, 4, 9, 16}
s2 = set(x*x for x in range(5)) #{0, 1, 4, 9, 16}
dic1 = {x:x*x for x in range(5)} #{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
dic2 = dict( (x,x*x) for x in range(5)) #{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

dic = {x+y: (ord(x),ord(y)) for x in 'ab' for y in 'cd'}
print(dic) #{'ac': (97, 99), 'ad': (97, 100), 'bc': (98, 99), 'bd': (98, 100)}

c = {c.lower() : c+'!' for c in 'spam'} #{'a': 'a!', 's': 's!', 'p': 'p!', 'm': 'm!'}

 4、生成器表达式

把列表推导式的[]换成()
优点:省内存,一次只生成一个值在内存中
l_new = (i for i in range(50) if i%2==0)
for i in l_new:
    print(i)
# print(next(l_new))
# print(next(l_new))
# print(next(l_new))
# print(next(l_new))

例1、将names=['egon','alex_sb','wupeiqi','yuanhao']中的名字全部变大写 

# 方法一
names=['egon','alex_sb','wupeiqi','yuanhao']
names_new = [i.upper() for i in names]
print(names_new)

# 方法二
names=['egon','alex_sb','wupeiqi','yuanhao']
name2 = map(lambda x:x.upper(),names)  #map得到的结果仍然是个迭代器
print(list(name2))

例2、将names=['egon','alex_sb','wupeiqi','yuanhao']中以sb结尾的名字过滤掉,然后保存剩下的名字长度  

names=['egon','alex_sb','wupeiqi','yuanhao']
names2 = [len(i) for i in names if not i.endswith('sb')]
print(names2)

 例3、求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数) 

with open('data.txt','r') as f:
    l = [len(line) for line in f]
print(max(l))

#还可以再精简些
with open('data.txt','r') as f:
    print(max(len(line)) for line in f)

  例4、求文件a.txt中总共包含的字符个数?思考为何在第一次之后的n次sum求和得到的结果为0?(需要使用sum函数) 

with open('data.txt','r') as f:
# with是上下文管理器,必须在with 里面,在外面print(g)的话,这时候文件已经关闭了
    s = (len(line) for line in f)#s此时是一个迭代器,一次在内容中只有一个值,所以print()函数必须在with里面,不然文件关闭了之后,就不能通过next()取值了
    # print(next(s))
    # print(next(s))
    print(sum(s))

 

posted @ 2021-04-03 18:13  cheng4632  阅读(93)  评论(0编辑  收藏  举报