Python 进阶之路 (八) 最用心的推导式详解 (附简单实战及源码)

44次阅读

共计 4259 个字符,预计需要花费 11 分钟才能阅读完成。

什么是推导式
大家好,今天为大家带来问我最喜欢的 Python 推导式使用指南,让我们先来看看定义~
推导式(comprehensions)是 Python 的一种独有特性,推导式是可以从一个数据序列构建另一个新的数据序列的结构体。一般有三种使用最多的推导式:

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

使用推导式可以简化代码的同时提高效率,在我的个人使用场景中,用的最多的还是列表推导式,接下来我会一一介绍这三种常见的推导式,最后通过一个简单实战发现推导式的高效之处
列表推导式(list comprehensions)
模板
首先,让我们看看使用列表推导式的基础模板:
[expression for item in list if conditional]
简单来说,遍历一个 list,得到每一个元素 item,我们相对 item 进行哪些操作,写在 expression 里就可以,如果对筛选有什么条件,可以放在 if 后面
下面可以通过大量实例帮助大家理解
使用实例
先看第一个小栗子,在这里我们用 for 循环常规遍历一个字符串‘human’,把每一字母作为元素放在一个叫 h_letters 的数组里面:
h_letters = []
for letter in ‘human’:
h_letters.append(letter)

print(h_letters)

Out:[‘h’, ‘u’, ‘m’, ‘a’, ‘n’]

如果我们根据列表推导式的定义模板,可以简化如下:
h_letters = [letter for letter in ‘human’]
print(h_letters)

Out: [‘h’, ‘u’, ‘m’, ‘a’, ‘n’]
这样的话便捷了很多,看上去也很容易理解,这里我们在 expression 部分什么都没有些,只是提出了每个元素而已,运行时的 python 执行方式如下:

我们可以在 expression 的部分进行很多操作,比如:
h_letters = [letter.upper() for letter in ‘human’ ]
print(h_letters)

Out: [‘H’, ‘U’, ‘M’, ‘A’, ‘N’]
这样我们可以很容易的实现字母的大小写转化
同样的,我们可以在 if 后面写出筛选条件,比如这里,我们想要提出从 -20 ~ 20 中所有能被 3 整除的正数:
result = [num for num in range(-20,20)
if num %3==0 and num > 0]

print(result) #多个条件可以用 and 连接

Out: [3, 6, 9, 12, 15, 18]

列表推导式的实际应用场景十分广泛,它于 lambda 不同,是真正好理解,提成效率的 python 特性之一,这里相信聪明的你已经想到了更多用法!
字典推导式(dict comprehensions)
模板
让我们看先来看使用字典推导式的基础模板:
{key:value for key,value in existing_data_structure}
这里和 list 有所不同,因位 dict 里面有两个关键的属性,key 和 value,大同小异,我们现在的 expression 部分可以同时对 key 和 value 进行操作
下面来看最常见的应用
使用实例
首先最实用的功能莫过于可以实现一个 dict 的 key,value 值互换:
person = {‘name’:’xiaobai’,’city’:’paris’}
person_reverse = {v:k for k,v in person.items()} #简单互换 key 和 value 的值即可

print(person_reverse)
Out: {‘xiaobai’: ‘name’, ‘paris’: ‘city’}

这里就非常方便了用字典推导式,不然的话只能用 for 循环,会稍微麻烦一些。让我们再看下一个很巧的例子:
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()}

print(num_frequency)

Out: {‘a’: 15, ‘b’: 23, ‘d’: 4}

这里使用的就比较灵活,我们有一个数据,key 是字母的大小写混在一起,我们想统计同一个 key(大小写都包括)所对应的数字出现总和,所以在新建的 num_frequency 字典用使用了推导式,这里我们遍历的是 dict.keys() 配合 dict.get() 方法
再比如下面的例子:
fruit = [‘apple’,’banana’,’organge’,’mango’,’peach’]

fruit_len = {f:len(f) for f in fruit}
print(fruit_len)

Out:{‘apple’: 5, ‘banana’: 6, ‘organge’: 7, ‘mango’: 5, ‘peach’: 5}

我们有一个 fruit 的 list,现在想要得到每一种水果的单词长度,就可以通过图中所示的方法实现,非常容易
最后再来看一个字典推导式配合枚举(enumerate)的例子:
fruit = [‘apple’,’organge’,’banana’,’mango’,’peach’]

fruit_positon = {v:i for i,v in enumerate(fruit)}
print(fruit_positon)

Out: {‘apple’: 0, ‘organge’: 1, ‘banana’: 2, ‘mango’: 3, ‘peach’: 4}

还是用刚才的 list,这次我们得到的 key 是 fruit 的每个元素,value 则是该元素在 fruit 所属的 index
集合推导式(Set comprehensions)
模板
让我们看先来看使用集合推导式的基础模板:
{expression for item in Sequence if conditional}
其实集合推导式和 list 的推导式很像,但是既然是结合,肯定会配合利用 Set 的属性来实现我们的目的,如果你还对 Set 这种数据结构不够了解,可以参考我之前的文章:Python 进阶之路 (四) 先立 Flag, 社区最全的 Set 用法集锦
下面来看最常见的应用
使用实例
首先,我们来看一个根据 Set 值唯一的特性的例子,我们有一个 list 叫 names,用来存储名字,其中的数据很不规范,有大写,小写,还有重复的,我们想要去重并把名字的格式统一为首字母大写,实现方法便是用 Set 推导式:
names = [‘Bob’, ‘JOHN’, ‘alice’, ‘bob’, ‘ALICE’, ‘James’, ‘Bob’,’JAMES’,’jAMeS’]
names_standard = {n[0].upper()+n[1:].lower() for n in names}

print(names_standard)
Out: {‘John’, ‘Bob’, ‘James’, ‘Alice’}

这里就不再举很多的其他例子了,因为使用的方式多种多样,剩下的就靠广大人民群众的智慧自行开发即可!
简单实战
现在让我们来看一个比较综合的例子!我们现在手里有一个英文字典的 dictionary.txt 文件,包含从 A~Z 的单词
具体需求:我们想要找到长度大于 5 的正反拼写都具有实际含义的单词
我们现在会通过各种推导式来实现这个目标,我会在文章最后把 txt 文件及 Python 文件下载链接附上,这样大家如果先要练习可以自行下载
首先,我们的初始目录结构如下:

这里我新建了一个 test 文件夹,把 dictionary.txt 文件和 python 文件放在一起方便读取,开始之前,先大概看下 txt 文件长什么样子:

第一步:读取 dictionary.txt 中的单词,选出长度大于 5 的
import os
print(os.getcwd())
with open(‘dictionary.txt’) as dictionary_file:
words = (line.rstrip() for line in dictionary_file)
words_over_five_letters = [w for w in words if len(w)>5 ]

这里通过列表推导式 words_over_five_letters 用来存储所有长度大于 5 的单词
第二步:将上一步选出的单词全部倒序存贮
reversed_words ={
word[::-1]
for word in words_over_five_letters
}
通过 set 推导式非常容易的实现
第三步:通过 if 条件筛选得出结果
reversible_words = [
word
for word in words_over_five_letters
if word in reversed_words
]

for word in reversible_words[0:20]:
print(word)

Out:
abrood
agenes
amaroid
amunam
animal
animes
bruted
darter
decart
decurt
deedeed
deflow
degami
degener
degged
deified
deifier
deliver
denier
这里最后共有 203 个结果,我们只看了前 20 个,验证方法就是只要长度大于 5 的单词同时存在于 reversed_words 和 words_over_five_letters 即可
完整代码如下:
import os
print(os.getcwd())
with open(‘dictionary.txt’) as dictionary_file:
words = (line.rstrip() for line in dictionary_file)
words_over_five_letters = [w for w in words if len(w)>5 ]

reversed_words ={
word[::-1]
for word in words_over_five_letters
}

reversible_words = [
word
for word in words_over_five_letters
if word in reversed_words
]

for word in reversible_words[0:20]:
print(word)
资料下载

dictionary.txt
dictionary.py

总结
这次为大家总结了 python 里面常见的三种推导式相关用法以及最后的小实战环节,希望大家喜欢,双击 666 点个赞吧!!

正文完
 0