查看原文
其他

优雅简洁的列表推导式

2017-11-16

作者 大邓

优雅的列表推导式

最近比较累,给自己放了很长的假。使用廖雪峰网站学习时一开始学过列表推导式这方面的知识,但不知道有什么用,也没觉得好看简洁。但接触的多了,用的多了之后,发现推导式确实好用。

使用推导式可以简化代码,方便阅读理解。借助推导式,可以代替以下功能:

  1. 替换for循环,压缩代码行数

  2. 使用lambda表达式,实现map()、filter()、reduce(),代码便于理解

一、替换for循环

因为简单易用,列表是python中常用的数据类型。但是列表往往需要使用for循环代码块,第一个缺点是代码可读性降低,第二个缺点是代码行数大大增加。

使用列表推导式就能消除以上两点,而且效率还会略有提高。

我们先看一个例子,[0,1,2,3,4,5,6,7,8,9]中选取偶数,并计算偶数的平方将其加到一个新列表中。我们先看看常见的实现方式

#生成0-9的列表
numbers = range(10)
new_list = []

#将计算结果加到new_list中
for n in numbers:    if n%2==0:        new_list.append(n**2)

print(new_list)
[0, 4, 16, 36, 64]

再来看看推导式实现方式

numbers = range(10)

new_list = [n**2 for n in numbers if n%2==0]

print(new_list)

只用了三行就实现了上面好多行的代码应有的功能。

[0, 4, 16, 36, 64]

我们再来比较下运行效率,为了方便计算,我们将使用timeit模块计算两者运行10000次所消耗时间的大小,用时最少表示其运行效率更高。

import timeit

#推导式运行时间
print(timeit.timeit('[n**2 for n in range(10) if n%2==0]', number=10000))


#for代码
def forcodeblock():    new_list = []    for n in range(10):        if n%2==0:            new_list.append(n**2)    return new_list

#for代码块运行时间
print(timeit.timeit('forcodeblock()',globals=globals(),numbers=10000))
0.05234622399802902 0.07795589299712447

看,用列表推导式运行时间更短,更快。

二、实现map()的功能

lambda表达式功能类似于函数,但是没有名字的函数。我们在推导式中可以加入lambda表达式,进而实现map()的功能。

map(function,iterable)

map函数是对iterable中的每一个元素施行function函数计算,返回可迭代结果(如列表)。

直接看例子,解说map及推导式的实现方式

公制时间转换,将以秒计算单位转化为以分钟计时,需要除以60.

#存储时间的列表
time_list = [60,120,3600,1200,600]

#使用map实现
new_time_list = map(lambda x:x/60, time_list)
print(new_time_list)
[1,2,60,20,10]

再来看看推导式实现方式:

#存储时间的列表
time_list = [60,120,3600,1200,600]

#使用map实现
new_time_list = [x/60 for x in time_list]
print(new_time_list)

三、实现filter()功能

filter意思是过滤剔除。

filter(function,iterable)

filter跟map类似,对iterable每个元素计算function(该函数计算结果为布尔值),如果该元素function值为布尔值为1,则保留该元素。最终输出所有保留的元素。

现在我们看一个0-9的数组,只保留奇数。

numbers = range(10)

#奇数
uneven = filter(lambda x:x%2,numbers)
print(uneven)
[1,3,5,7,9]

再来看看,列表推导式实现filter。这里只给出列表中对应位置元素值为1.

uneven = [x for x in numbers if x%2]
print(uneven)
[1,3,5,7,9]

四、实现reduce()功能

reduce(function,iterable)功能不好说,我举个例子,大家自己琢磨一下。

#对[1,2,3,4]进行求和运算,使用reduce是这样子的。 (((1+2)+3)+4)

reduce不限于四则运算,只要reduce第一个参数是运算规则,第二个参数是可迭代对象

from functools import reduce

#对0-9进行求和
numbers = range(10)

reduced_sum = reduce(lambda x,y:x+y, numbers)

print(reduced_sum)

推导式方式代码:

numbers = range(10)

reduced_sum = sum([x for x in numbers])

五、带条件的推导式

5.1 一个条件

numbers = range(10)

#奇数
uneven = [x/2 for x in numbers if x%2==0]

print(uneven)
numbers = range(10)

#奇数
uneven = []
for x in numbers:    if x % 2 == 0:        x = x / 2        uneven.append(x)

print(uneven)

5.2 多个条件

#0-9中同时被2和6整除的数
divided = []
for x in range(10):    if x%2 == 0 :        if x%6 == 0:            divided.append(x)
#0-9中同时被2和6整除的数
divided = [x for x in range(10) if x%2==0 if x%6==0]

5.3 if-else

推导式很少看到if-else,如果想实现if-else该咋整。if-elif-else与if-else类似。直接看案例

for x in range(10):      if x >= 5:        x + 1    else:        x+5

推导式实现

[x+1 if x>=5 else x+5 for x in range(10)]

六、嵌套推导式

有时候要处理列表的列表,这个有点难度。比如生成列表的列表,对矩阵进行转置,或者flatten矩阵为列表。

6.1 flatten

list_of_list = [[1,2,3],[4,5,6],[7,8]]

#flatten
print([y for x in list_of_list for y in x])
[1, 2, 3, 4, 5, 6, 7, 8]

6.2 生成矩阵

生成3行4列的矩阵,常规手法

matrix=[]

for x in range(3):    nested = []    matrix.append(nested)    for row in range(4):        nested.append(0)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

推导式实现

matrix=[[0 for col in range(4)] for row in range(3)]

print(matrix)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

6.3 矩阵转置

在矩阵中,行列互换。

[[1,2,3], [4,5,6], [7,8,9]] 变成 [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

常规的实现方式转置

transposed = []

for i in range(3):     transposed_row = []     for row in matrix:            transposed_row.append(row[i])     transposed.append(transposed_row)

推导式实现矩阵转置

list_of_list = [[1,2,3],[4,5,6],[7,8,9]]

print([[row[i] for row in matrix] for i in range(3)])
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

历史文章:

数据采集

selenium驱动器配置详解

icrawler:强大简单的图片爬虫库

抓取单博主的所有微博及其评论

爬虫神器PyQuery的使用方法

pyquery一些自定义的用法

【视频】猫途鹰网站评论数据抓取

【视频讲解】在scrapy框架中如何使用selenium?

【实战视频】使用scrapy写爬虫-爬知乎live

简易SQLite3数据库学习

【视频教程】对视频进行基本操作

【视频】抓包小练习-B站评论数据抓取

fake-useragent库:值得花2分钟学习的库

【视频】爬取饿了么平台上的门店信息

如何抓取视频资源-以头条视频为例

当爬虫遭遇验证码,怎么办

【视频】手把手教你抓美女~

【视频】有了selenium,小白也可以自豪的说:“去TMD的抓包、cookie”

【视频】快来get新技能--抓包+cookie,爬微博不再是梦

【视频教程】用python批量抓取简书用户信息

识别假货有绝招,就用python爬淘宝评论

用Python抓取百度地图里的店名,地址和联系方式

文本处理分析

gensim:用Word2Vec进行文本分析

RAKE:快速自动抽取关键词算法

对于中文,nltk能做哪些事情

用nltk计算词语间的点互信息值PMI

Python NLP中的五大英雄

用SenticNet库做细粒度情感分析

如何对csv文件中的文本数据进行分析处理

复杂网络分析数据准备篇

文本分析之网络关系

用词云图解读“于欢案”

基于共现发现人物关系的python实现

用pyecharts制作词云图

图片数据处理

OpenCV:快速入门图片人脸识别

好玩的OpenCV:图片操作的基本知识(1)

好玩的OpenCV:图像操作的基本知识(2)

OpenCV:计算图片有多色

如何对数据进行各种排序?

其他

迅雷不给力,我DIY了个下载器

【视频】初学者必看:python环境配置

开扒皮自己微信的秘密

初识装饰器函数

计算运行时间-装饰器实现

花十分钟,给爱机安装个MongoDB

chardet库:轻松识别文件的编码格式

使用Python登录QQ邮箱发送QQ邮件

WTF Python: 开启你的懵逼模式

8行代码实现微信聊天机器人

WTF Python: 开启你的懵逼模式

WTF Python:开启懵逼模式第二弹

使用Python+OpenCV进行面部合成

十分钟学会用Flask发邮件


十分钟入门常用的json库

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存