Python列表解析/推导

列表解析:

什么是列表解析/推导(list comprehension):

Python列表解析是一种Python的语法,使用这种语法,可以遍历列表中的元素并进行特定的操作“和/或”过滤,并生成一个新的列表。

列表解析的作用:

列表解析可以将原本需要多行编写的代码简化为一行,并且可以带来很高的可读性和逼格,某些时候还可以让你少起一个变量名(这一点也很有用),最重要的是可以带来更高的效率(因为它再循环时调用了一些更底层的函数)

什么时候要用列表解析:

当需要对某个可迭代对象中的元素,进行某些遍历的操作、过滤时,便可以采用列表解析。

列表解析的定义:

[expr for iter_var initerable] 和 [expr foriter_var in iterable if cond_expr],其中第一种在遍历列表时是不包含过滤操作的,第二种包含一个过滤条件。
expr 是一个表达式(可以是一个方法、函数、lamda表达式等),iterable 是一个可迭代的对象(一般是一个列表或元祖),iter_var 是 iterable 中的一个元素,cond_expr是一个条件表达式。
列表解析也可以理解为一个函数,结构如下:
def func(iterable):
    m_list = []
    for iter_var in iterable:
        m_list.append(exper(iter_var))
        return m_list

有过滤条件的:

def func(iterable):
    m_list = []
    for iter_var in iterable:
        if cond_expr:
            m_list.append(exper(iter_var))
        return m_list
列表解析的操作必须是一个表达式:

列表解析 [expr for iter_var initerable] 中的 expr 必须是一个表达式(如 lamda, function, 类中的方法)
例如:
# 将 string_list_list 中的 ["hello"] 都换成 ["bye"]
string_list_list = [["hello"], ["bye"], ["hello"], ["bye"]]
[string_list[0] = "bye" for string_list in string_list_list if string_list[0] == "hello"]
相当于:
for string_list in string_list_list:
    if string_list[0] == "hello":
        string_list[0] = "bye"
但是 前者的列表解析是错误的,因为 赋值操作 string_list[0] = "bye" 并不是一个表达式,而是一个语句。而列表解中的 expr 析必须是一个表达式
如果想用列表解析完成此例子中的赋值操作,可以使用具体的等价表达式来进行:
[string_list.__setitem__(0, "bye") for string_list in string_list_list if string_list[0] == "hello"]
表达式,语句又很么区别呢,简单的来说,表达如 2*3,调用函数,调用方法等,表达式一定有一个值(所以在交互式的python解释器中,输入一个表达式执行后必然有一个结果)。
语句是一段可执行的代码。如if 语句,赋值语句 for语句等。语句本身并没有一个值(以在交互式的python解释器中,输入一个语句后并不会有立即的结果)
通俗的来讲列表解析:
即将可迭代(iterable)对象中的每一个元素(iter_var),经过expr处理后的内容,加入到新的列表中,如果有过滤条件(cond_expr),则将满足过滤条件的内容加入到新的列表,最后将新的列表返回。

列表解析的地位:

Python 中还有与列表解析相近功能的内建函数,如:
map() # 对可迭代对象中的元素进行某些操作
reduce() # 叠加可迭代对象中的元素
filter() # 过滤可迭代对象中的元素
列表解析加入Python的时间要晚于这三个内建函数,并且列表解析在功能上基本可以取代这三个函数,所以如果你还不了解这三个函数的用法,学会列表解析后基本上也不需要能使用它们了。
在列表解析之后,又有生成器表达式、字典解析/推导、集合解析/推导加入到Python中来,但他们的使用方法鱼列表解析也非常相近,本文后面也会讲到。

列表解析的实际用例:

例1:

数据:

int_list = [1, 45, 54, 23, 6, 123, 32, 2]

将列表中的每个元素加1:

int_list = [x + 1 for x in int_list]

相当于传统写法:

for x in int_list:
    m_int_list.append(x + 1)
int_list = m_int_list

得到输出:

for x in int_list:
    m_int_list.append(x + 1)
int_list = m_int_list
如果只想将奇数加1呢:

加一个过滤条件即可:

int_list = [x + 1 for x in int_list if x % 2]

也可以写成:

def func(x):
    return x + 1

int_list = [func(x) for x in int_list if x % 2]

相当于传统写法:

for x in int_list:
    if x % 2:
        m_int_list.append(x + 1)
int_list = m_int_list

得到输出:

print(int_list )
[2, 46, 24, 124]
例2:

某文本内容如下:

/root/test

acute exactly fabric
sustain
disarm assemble
cabin cheek

crust league minor

misunderstand shy

succeed vacation asleep bitterly custom

读取文件并去除每一行末尾的换行符:

with open("/root/test") as fd:
    contest = [line.rstrip("\n") for line in fd.readlines()]

相当于传统写法:

with open("/root/test") as fd:
    contest = []
    for line in fd.readlines():
        contest.append(line.rstrip("\n"))

得到输出(注意空行还未被去除):

print(contest)
['acute exactly fabric', 'sustain', 'disarm assemble', 'cabin cheek', '', 'crust league minor',
 '', 'misunderstand  shy','', 'succeed vacation asleep bitterly custom']

进一步的,如果想得到一行内容超过10个字符的行呢:

加一个过滤条件即可

with open("/root/test") as fd:
    than10_contest = [line.rstrip("\n") for line in fd.readlines() if len(line) > 10]

相当于传统写法:

with open("/root/test") as fd:
    than10_contest = []
    for line in fd.readlines():
        if len(line) > 10:
            than10_contest.append(line.rstrip("\n"))

得到输出:

print(than10_contest)
['acute exactly fabric', 'disarm assemble', 'cabin cheek', 'crust league minor',
 'misunderstand shy', 'succeed vacation asleep bitterly custom']

再进一步的,如果想将每个单词的首字母都大写呢:

再嵌套一层for循环即可

with open("/root/test") as fd:
    up_than10_contest = [words.capitalize() for line in fd.readlines() if len(line) > 10 
                         for words in line.rstrip("\n").split(" ")]

相当于传统写法:

with open("/root/test") as fd:
    up_than10_contest = []
    for line in fd.readlines():
        if len(line) > 10:
            for words in line.rstrip("\n").split(" "):
                up_than10_contest.append(words.capitalize())

得到输出:

print(up_than10_contest)

['Acute', 'Exactly', 'Fabric', 'Disarm', 'Assemble', 'Cabin', 'Cheek', 'Crust', 'League', 'Minor', 'Misunderstand',
 'Shy', 'Succeed', 'Vacation', 'Asleep', 'Bitterly', 'Custom']


生成器表达式:

pass

字典推导:

pass

集合推导:

pass

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值