python 推导式有什么用呢_Python进阶系列:细讲Python推导式

2e2eb9389b504fc2fb72e6d2e452141591ef6d4f.jpeg?token=85556a74f38d0cb90e3f3e6374a04630&s=741AC83384C07EEA4B54D6E40300E021

前言

由于Python的良好生态,很多时候我们的程序只是通过调用别人写好的方法即可实现功能。

不过,很多时候我们还是需要处理序列。不管是入门中还是早已入门的小伙伴,对于处理序列毫无疑问会选择用for循环。但在Python中还有一种更高效更简洁的处理序列方式——推导式。本文详细探讨关于推导式的细节。

本文重点

学习推导式推导式的优缺点如何合理使用推导式推导式可能的进化本文字数2000+,适合已入门Python又希望水平有所提升的小伙伴。

原创不容易,请点击关注按钮,多多支持~

for循环有啥不好,非要学推导式?

我们来看一个例子,如何把一个数值列表中大于0的数值筛选出来。下图给出for循环的做法

2934349b033b5bb5e2ca226b375c263db700bc9d.jpeg?token=f95b59f876ee1216d7ad60741ce29a78&s=E9D0A34252B6866E1454A8030000A0C2

可以看到for循环还是妥妥地把问题解决,代码并不复杂。 分析代码与原问题的表达对应关系:

行5,表达从数值列表取出数值。行6,表达"大于0的数值筛选出来"但原问题没有提及到创建一个用于保存结果的列表和如何把结果加入结果列表。上面的代码中的行4与行7,都是多余的动作。是时候让推导式出场了

738b4710b912c8fc1e7d3b11fd8c6141d48821f0.jpeg?token=fb5ab6433d73912690eac4827a3ec363&s=E1F0A36653F496685CFDDD070000E0C2

上图是一种比较"官方"的写法,把整个推导式写到一行里,我更喜欢下图的写法。

a5c27d1ed21b0ef4a4fe8cd2dc4ba2de80cb3ebf.jpeg?token=cc322fda715e392ed255e32a2b8dd470&s=E1F0A36643F0BF681CE9D90B0000E0C1

这就是列表推导式,很简单吧。看起来其实与之前的for循环写法差不多。但推导式有以下好处。

不需要像for循环那样,先定义一个列表,然后在循环中编写如何把结果放入列表的代码。表达更为清晰了,推导式的每个部分都与原问题的表达一一对应。行15,表达了 我要把什么样的东西放入结果中,这里只有一个n,表示符合要求的数值。行16与行17与之前for循环分析是一致。注意看,这里不再需要写冒号了。推导式的外面用一个[]包围着,表示结果是一个列表。推导式的性能更好。在序列的数据量不大的情况下推导式的性能优势不会太明显,如果序列的元素数量成千上万,那么推导式比for形式性能通常优胜2倍以上。通过对比学习推导式

觉得怎么样,推导式是不是语义表达好的同时性能又高呢。下面通过与for循环形式对比来学习推导式的写法。 图中左边是for循环,右边是推导式

b7003af33a87e9506e80c9aa11b7a047f9f2b4f0.jpeg?token=4e87144b16c570001c2cd60820462d03&s=C9E08342CEA7B77C5ED0241F0000C0C3

红框部分表示遍历序列,可以看到两者形式一样,但注意,推导式不需要在最后写冒号

42a98226cffc1e17586e830a481f0507728de948.jpeg?token=ce6eda7419ea8cd3459061bdda213762&s=E9508346CEA2B76C46E1401D0000C0C2

同样地,上图红框表示如何判断每个元素,这里表示过滤的条件。我们可以写各种各样复杂的判断条件。

0e2442a7d933c89585200ffbd09c80f483020063.jpeg?token=4ce416c8def9456dfa35b3bd7bc6e905&s=E9F1A342CEEEBF7E4ED5441D0000D0C2

上图红框是推导式最后一部分,他决定了输出结果比如说,如果希望每个输出值是原来的两倍,我们就可以写 n*2结果可以是各种各样的类型,比如红框部分如果写 f'值:{n}',那么结果就是一系列的字符串。更进一步

我们来看一个稍微复杂点的例子。 假设我们有多个文件,每个文件都有多行数值(都是整数),行数不确定。如图:

8c1001e93901213feb4f4d715568c5d52e2e95b6.jpeg?token=39b9f0aac5c59546bc82929ace2c88e7&s=41A03C72132B55241CD5D1DA000050B3

现在需要把多个这样的文件的所有数值拿出来,然后把小于50的数值筛选出来作为结果,并且标注每个数值的来源文件。 下图是基本数据的定义

adaf2edda3cc7cd942c6b4a13b8ed23bb90e9177.jpeg?token=97f534eb9a89f3f3d96d879067f49858&s=E9E08346CBE09D701CD9F5060000E0C3

方法 get_nums_from_file 不是这里的重点,我们只需要知道,给他一个文本路径,他会读取文件中的每行的整数,以返回一个整数列表这个问题可以描述为"列表中的元素还可以提取出一个列表",这样的情况下同样可以用推导式。如下:

242dd42a2834349b7f89b882cb65e6ca37d3beba.jpeg?token=435c2ae3c9c7ebb3dcc3dc292cc7b1c9&s=61D0A366CFACB7700CF8C40F0000A0C2

其实与普通的for循环嵌套是差不多的套路行38,首先遍历paths列表行39,在上一个循环中获取文件中的整数列表再次遍历这个整数列表行40,对应原问题的筛选条件。行37,这里可以使用下方两个for的变量f和n,因此可以轻而易举找到每个数值的来源有时候不应该强行使用推导式

我们很容易犯的一个错误是,手上拿着一个锤子,看啥都认为是钉子,更何况拿着的是一个雷神之锤。

推导式简洁又高效的好处,很容易让人着迷于使用他来解决一切的集合处理问题。我们接着上面的需求来说明。 现在需求不仅仅过滤小于50的数值,而是取出"小于所在文件的所有数值的平均",并且结果需要显示该文件的平均值。 下面是推导式的解决方法:

4bed2e738bd4b31c89f8ae1c8559d47b9c2ff8e0.jpeg?token=4fb70856d1d68d6239772fc8a638ff41&s=A9E0C306DBECB3720C41410F0000F0C2

推导式最大的问题在于无法在过程中建立临时变量这个需求下,由于没法用临时变量保存一个文件的平均值,因此导致多次求平均,不仅代码结构乱,而且效率还很低。这时候老老实实使用for循环是个很好的选择。如下:

d043ad4bd11373f06b0c4b17a580b8fffaed049e.jpeg?token=6ec59fd7188457f277987d95fb517d5e&s=E9F0AB425EA9BF760C414407000070C2

未来,推导式可能的进化

Python的推导式其实来源于函数式编程中的思想,目前市面上的几门面向对象编程语言都加入了相关方面的语法,未来Python的推导式可能会参考他们从而改进自身的推导式语法。如图为C#的Linq,特点是他允许在过程中定义临时变量。

77c6a7efce1b9d166bd6ac59f151478b8c54640c.jpeg?token=b5ba8ba16dfe980be58492d8518c93cc&s=21512366DFE099700C50140A0000E0C2

可以看到,如果Python的推导式加入这样的语法功能,那么本文说的推导式的缺点就不再出现。Python的推导式在未来的进化值得期待。

小结

在处理序列时,推导式是一个高效简洁的方式当需求需要在循环中创建各种临时的状态数据时,推导式就不再适合处理。建议考虑使用for循环。在Python中,推导式很多时候被当作是否熟悉Python的标志之一,同时推导式也存在许多争议,我们应该清楚了解推导式再谈如何应用,毕竟任何技术都必需在适当的地方才能发挥最大的作用。

你已经学会了推导式了吗?平时使用for循环比较多还是推导式比较多?

如果觉得本文对你有所帮助,记得关注、评论、转发、收藏噢~ 私信我"python",即可获得按水平领域分类好的Python资料,还会不定期更新有用的Python技巧。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值