Python 中的推导式

推导式(解析式)

推导式comprehensions(又称解析式),是Python的一种独有特性。

推导式是可以从一个数据序列构建另一个新的数据序列的结构体。 共有三种推导,在Python2和3中都有支持:

  • 列表(list)推导式
  • 字典(dict)推导式
  • 集合(set)推导式

range() 函数

python的 range() 函数可用来创建一个整数列表,一般用在 for 循环中.

range()语法:

range(start, stop[, step])

start: 计数从start开始,默认是从0开始(闭区间),如:range(5)等价于range(0,5).

stop: 计数到stop结束,但不包括stop(开区间).如:range(0,5)是[0, 1, 2, 3, 4],不包含5.

step: 步长,相邻两个值的差值,默认为1.如:range(0,5)相当于range(0, 5, 1).

列表推导式是通过一个可迭代对象来生成列表的, range()可以说是列表推导式中最常用的可迭代对象了.对列表推导式来说, range() 是其中的精髓之一.


列表推导式

基本格式为:

[表达式 for 变量 in 列表] 或者 [表达式 for 变量 in 列表 if 条件]

具体可分为两种:

[x for x in data if condition]

此处if主要起条件判断作用,data数据中只有满足if条件的才会被留下,最后统一生成为一个数据列表。

[exp1 if condition else exp2 for x in data]

此处if...else主要起赋值作用,当data中的数据满足if条件时将其做exp1处理,否则按照exp2处理,最后统一生成为一个数据列表。

例1:过滤掉长度小于或等于3的字符串列表,并将剩下的转换成大写字母:

>>> names = ['Bob','Tom','alice','Jerry','Wendy','Smith']
>>> new_names = [name.upper()for name in names if len(name)>3]
>>> print(new_names)
['ALICE', 'JERRY', 'WENDY', 'SMITH']

例2:生成间隔5分钟的时间列表序列:

>>> time = ['%.2d:%.2d'%(h,m )for h in range(24) for m in range(0,60,5) ]
>>> print(time)
['00:00', '00:05', '00:10', '00:15', '00:20', '00:25', '00:30', '00:35', '00:40', '00:45', '00:50', '00:55', '01:00', '01:05', '01:10', '01:15', '01:20', '01:25', '01:30', '01:35', '01:40', '01:45', '01:50', '01:55', '02:00', '02:05', '02:10', '02:15', '02:20', '02:25', '02:30', '02:35', '02:40', '02:45', '02:50', '02:55', '03:00', '03:05', '03:10', '03:15', '03:20', '03:25', '03:30', '03:35', '03:40', '03:45', '03:50', '03:55', '04:00', '04:05', '04:10', '04:15', '04:20', '04:25', '04:30', '04:35', '04:40', '04:45', '04:50', '04:55', '05:00', '05:05', '05:10', '05:15', '05:20', '05:25', '05:30', '05:35', '05:40', '05:45', '05:50', '05:55', '06:00', '06:05', '06:10', '06:15', '06:20', '06:25', '06:30', '06:35', '06:40', '06:45', '06:50', '06:55', '07:00', '07:05', '07:10', '07:15', '07:20', '07:25', '07:30', '07:35', '07:40', '07:45', '07:50', '07:55', '08:00', '08:05', '08:10', '08:15', '08:20', '08:25', '08:30', '08:35', '08:40', '08:45', '08:50', '08:55', '09:00', '09:05', '09:10', '09:15', '09:20', '09:25', '09:30', '09:35', '09:40', '09:45', '09:50', '09:55', '10:00', '10:05', '10:10', '10:15', '10:20', '10:25', '10:30', '10:35', '10:40', '10:45', '10:50', '10:55', '11:00', '11:05', '11:10', '11:15', '11:20', '11:25', '11:30', '11:35', '11:40', '11:45', '11:50', '11:55', '12:00', '12:05', '12:10', '12:15', '12:20', '12:25', '12:30', '12:35', '12:40', '12:45', '12:50', '12:55', '13:00', '13:05', '13:10', '13:15', '13:20', '13:25', '13:30', '13:35', '13:40', '13:45', '13:50', '13:55', '14:00', '14:05', '14:10', '14:15', '14:20', '14:25', '14:30', '14:35', '14:40', '14:45', '14:50', '14:55', '15:00', '15:05', '15:10', '15:15', '15:20', '15:25', '15:30', '15:35', '15:40', '15:45', '15:50', '15:55', '16:00', '16:05', '16:10', '16:15', '16:20', '16:25', '16:30', '16:35', '16:40', '16:45', '16:50', '16:55', '17:00', '17:05', '17:10', '17:15', '17:20', '17:25', '17:30', '17:35', '17:40', '17:45', '17:50', '17:55', '18:00', '18:05', '18:10', '18:15', '18:20', '18:25', '18:30', '18:35', '18:40', '18:45', '18:50', '18:55', '19:00', '19:05', '19:10', '19:15', '19:20', '19:25', '19:30', '19:35', '19:40', '19:45', '19:50', '19:55', '20:00', '20:05', '20:10', '20:15', '20:20', '20:25', '20:30', '20:35', '20:40', '20:45', '20:50', '20:55', '21:00', '21:05', '21:10', '21:15', '21:20', '21:25', '21:30', '21:35', '21:40', '21:45', '21:50', '21:55', '22:00', '22:05', '22:10', '22:15', '22:20', '22:25', '22:30', '22:35', '22:40', '22:45', '22:50', '22:55', '23:00', '23:05', '23:10', '23:15', '23:20', '23:25', '23:30', '23:35', '23:40', '23:45', '23:50', '23:55']

例3: 求(x,y),其中x是0-5之间的偶数,y是0-5之间的奇数组成的元祖列表:

>>>list = [(x,y) for x in range(5) if x%2 == 0 for y in range(5) if y%2 == 1]
>>>print(list)
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]

例4: 求M中斜线1,5,9组成的列表:

>>>M = [[1,2,3],[4,5,6],[7,8,9]]
>>>list_1 = [M[x][x] for x in range(len(M)) ]
>>>print(list_1)
[1, 5, 9]

注意:

使用()生成generator:

将俩表推导式的[]改成()即可得到生成器。

multiples = (i for i in range(30) if i % 3 is 0)
print(type(multiples))

Output: <type 'generator'>

字典推导式

基本格式为:

{ key:value for key, value in existing_data_structure }

这里和list有所不同,因位dict里面有两个关键的属性,key 和 value,但大同小异,我们现在的expression部分可以同时对 key 和 value 进行操作 :

例1: 用字典推导式配合枚举的使用案例:

>>> strings = ['import','is','with','if','file','exception','shim','lucy']
>>> dict = {k:v for v,k in enumerate(strings)}
>>> print(dict)
{'import': 0, 'is': 1, 'with': 2, 'if': 3, 'file': 4, 'exception': 5, 'shim': 6, 'lucy': 7}

上题的k是字符串,v是序列。如果我们更换k v:

>>> strings = ['import','is','with','if','file','exception','shim','lucy']
>>> dict = {k:v for k,v in enumerate(strings)}
>>> print(dict)
{0: 'import', 1: 'is', 2: 'with', 3: 'if', 4: 'file', 5: 'exception', 6: 'shim', 7: 'lucy'}

其中,enumerate()函数参考:https://www.runoob.com/python/python-func-enumerate.html

例2:源数据的key是字母的大小写混在一起,我们想统计同一个字母(不论大小写)的key所对应的键值对的和:

nums = {'a':10,'b':20,'A':5,'B':3,'d':4}
num_frequency  = {k.lower():nums.get(k.lower(),0) + nums.get(k.upper(),0)
                  for k in nums.keys() }
#nums是字典,nums.get(k.lower(),0)的意思是在字典nums中查找小写Key
#找到了返回KEY对应的Value,否则返回参数0,nums.get(k.upper(),0)同上
print(num_frequency)
{'a': 15, 'b': 23, 'd': 4}

集合推导式

基础格式为:

{ expression for item in Sequence if conditional }

其实集合推导式和list的推导式很像,但是既然是集合,肯定会配合利用Set的特有属性来实现我们的目的。

例1:首先,我们来看一个根据Set值唯一的特性的例子,我们有一个list叫names,用来存储名字,其中的数据很不规范,有大写,小写,还有重复的,我们想要去重并把名字的格式统一为首字母大写,实现方法便是用Set推导式:

>>> names = [ 'Bob', 'JOHN', 'alice', 'bob', 'ALICE', 'James', 'Bob','JAMES','jAMeS' ]
>>> new_names = {n[0].upper() + n[1:].lower() for n in names}
>>> print(new_names)
{'Bob', 'James', 'John', 'Alice'}

拓展阅读

[1] Python Tutorial: Comprehensions

[2] Python常用的推导式

[3] python各种推导式(超级详细)

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