python笔记_列表解析

参考了一部分:http://tech.pro/tutorial/1554/four-tricks-for-comprehensions-in-python

list是python中十分重要的一种数据结构,生成新的list是python程序员每天都会进行的工作,除了机械的使用for循环,append函数等方式来生成列表,还可以考虑使用更加pythonic的方式来的到列表

一、什么是列表解析?

简单来说,列表解析(list comprehension)提供了一种优雅的生成列表的方法,能用一行代码代替十几行代码,而且不损失任何可读性。而且,性能还快很多很多

简单给个例子,如果我们需要0~100所有偶数组成的列表,正常的代码应该是这样的:

a=[]
for i in range(101):
    if i%2==0:
        a.append(i)

用列表解析来做就是这样的:

a=[x for x in range(101) if x%2==0]

简单的一行代码代替了4行代码

从上面的例子来看列表解析的语法其实不难,可以分成三个部分来看

  • x:我们需要的列表里面的结果(1st part)
  • for x in range(101):x来源——0~100的数字(2nd part)
  • if x%2==0:x成立的条件,如果不成立就不放在列表里了(3rd part)

例2,获取文本中所有单词的第1个字符

正常的代码

text="My house is full of flowers"
first_charts=[]
for word in text.split():
    first_charts.append(word[0])

列表解析的代码:

first_charts=[word[0] for word in text.split()]

从上面的这个例子可以看出,列表解析的第一部分也可以是任意一个表达式

例3,获取两个列表对应位的乘积

来个复杂的,list a=[2,3,4,5]; list b=[3,4,5,6],想要得到a,b对应位的乘积:

[i*j for i,j in zip(a,b)]

除了列表解析,还需要使用zip函数来帮忙,zip将a,b对应位打包起来,返回[[2,3][3,4][4,5][5,6]]

例4,带if else的列表解析

list a=['1','2','3','i','8'],现在想将a中所有能转化为数字的字符串转化为数字,不为数字的内容都转换成0,用列表解析可以这样写:

[int(i) if i.isdigit() else 0 for i in a]
out>>[1,2,3,0,8]

增加一点难度,如果list a=['1','2','3',4,5,'o','6'],如果不能转换成数字则为None,列表解析可以这样写:

[int(i) if str(i).isdigit() else None for i in a]
out>>[1, 2, 3, 4, 5, None, 6] 

从这个例子我们可以看到,在第一个部分,可以嵌套若干if else的语句在表达式里面。

例5,获取一个全0列表

有时候我们可能需要获取一个长度指定,全零或者全为某个值列表:

['ok' for i in range(10)]

得到一个长度为10的,全'ok'字符组成的列表

例6,略复杂的列表解析,获取列表中嵌套列表的元素,生成一个无嵌套的新列表

这个例子说起来挺拗口,实际上是想从[[1,2],[3,4,5],[6,7],[8]]这种列表中,把嵌套在列表中的元素解出来,得到[1,2,3,4,5,6,7,8],用列表解析可以这样写:

a=[[1,2],[3,4,5],[6,7],[8]]
[x  for i in a for x in i] 
out>>[1,2,3,4,5,6,7,8]

理解起来略有一点麻烦,for i in a,i为子列表,for x in i,x得到每个子列表中的值。这样的列表解析写法确实很难理解,所以有时候我们不要过分的使用复杂的列表解析。

例7,获取笛卡尔积

假设有三个配置列表

>>> a=['4k','8k','12k']                                                                                                                          
>>> b=['1','2,','3']                                                                                                                             
>>> c=['libaio','bio','directio'] 

我们想获取其笛卡尔积,列表解析的写法,得到:

[{'blocksize':x,'numjobs':y,'ioengine':z} for x in a for y in b for z in c] 

这样就得到一个包含所有参数项目的字典列表,避免了写若干个for循环

例8,获取所有可能的组合

假设有一个配置列表['a','b','c'],我们想获取所有的由a,b,c组成的字符串(可以重复使用,将顺序也考虑在内),列表解析需要配合itertools中的product函数:

from itertools import product
x=['a','b','c']
results = ["".join(i) for i in product(x, repeat=3)]
out>>['aaa', 'aab', 'aac', 'aba', 'abb', 'abc', 'aca', 'acb', 'acc', 'baa', 'bab', 'bac', 'bba', 'bbb', 'bbc', 'bca', 'bcb', 'bc                                            
c', 'caa', 'cab', 'cac', 'cba', 'cbb', 'cbc', 'cca', 'ccb', 'ccc']

例9,矩阵转置
考虑一个矩阵,matrix=[[1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12]],现在要获得他的转置矩阵,用列表解析仍然是一行:

transposed = [list(row) for row in zip(*matrix)]

matrix使用zip解开(完成转置),列表解析负责将结果生成原来的列表嵌套列表的模式

这个case也可以不用列表解析:

transposed = list(map(list, zip(*matrix)))

使用map函数也是可以的(顺便提一下)

二、列表解析快多少?

相比于for循环,列表解析的语法是由底层c语言实现的,它和使用for循环遍历pyobject对象相比,性能会有很大的提升,具体可以对比一下,定义两个函数:

def l1_true(L):
    a=[x*x for x in L]
    return
def l1_false(L):
    a=[]
    for i in L:
        a.append(i*i)
    return

L为range(10000),将这两个函数循环执行10000次,计算平均耗时得到:

l1_true:0.0007s
l1_false:0.0014s

从耗时来看,使用列表解析后生成同样列表,耗时是使用for循环的二分之一

使用例6的列表解析来对比

def l2_true(L):
    result=[x  for i in L for x in i]
    return
def l2_false(L):
    a=[]
    for i in L:
        for x in i:
            a.append(x)

L=[[i,i+1] for i in range(10000)],循环执行10000次对比结果为:

l2_true:0.0015
l2_false:0.0033

由上面两个例子可以看出,列表解析的将会大大提高python代码的执行效率,在实际工作中感觉也同样明显,应该尽量多使用列表解析

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,783评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,360评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,942评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,507评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,324评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,299评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,685评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,358评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,652评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,704评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,465评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,318评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,711评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,991评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,265评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,661评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,864评论 2 335

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,502评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,121评论 25 707
  • 《ilua》速成开发手册3.0 官方用户交流:iApp开发交流(1) 239547050iApp开发交流(2) 1...
    叶染柒丶阅读 10,356评论 0 11
  • 生活中我们常常自以为把想法说清楚了,就觉得别人能理解,但事实上还是没表达清楚,很多的矛盾也由此而来。今天晨读分享的...
    wukaili阅读 305评论 2 2
  • You don't think other people's understandings as the n...
    雪萦阅读 558评论 2 4