作者 | 天元浪子 责编 | 张文
来源 | 来自 CSDN 博客
某同学应聘 Python 岗位被录用。上班第一天,Leader 吩咐他写一个获取次日日期信息的函数。该同学信心满满地写下了这样一段代码, 然后就没有然后了。
import timedef get_next_date(): time.sleep(24*60*60) return time.strftime('%Y-%m-%d')
当然,这只是一个段子,相信没有 Python 程序员真的会写出这样的代码。不过,很多时候,我们写出来的代码尽管功能满足需求,效率也还说得过去,但可读性较差,且难以维护,和人们通常所说的简洁优美相去甚远。
那么,怎样才能写出传说中的简洁优美的 Python 代码呢?前几天,我在 Python 学习群里征集一个 Python 小题目的答案,借以了解程序员的编程习惯,分析影响程序员写出 Pythonic 代码的主要原因,最终总结出三条秘诀。题目如下:二维列表转置。
严格讲,Python 的列表并没有维度的概念。这里说的二维列表是指类似下面这样的列表。
[ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]
请实现二维列表的转置(行列互换,首行变首列,尾行变尾列,如下所示)。
[ [1, 4, 7], [2, 5, 8], [3, 6, 9] ]
这个活动得到了同学们的热情支持,甚至有同学们使用 Java 语言提交了自己的答案。对于这些同学,除了表示感谢,我无法回报更多,只能在能力所及的范围内,为每人提供 30 分钟的一对一服务,比如,代写作业、答疑等。
这是我收到的众多答案中的一个,并且很有代表性。
>>> a = [[1,2,3], [4,5,6], [7,8,9]]>>> a_copy = []>>> a_temp = []>>> a_size = len(a)>>> a_item_size = len(a[0])>>> for i in range(a_item_size): for j in range(a_size): a_temp.append(a[j][i]) a_copy.append(a_temp) a_temp = [] >>> a_copy[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
阅读这段代码的时候,最感吃力的是我需要记住 a_copy、a_temp 、a_size、a_item_size 等中间变量,否则读不懂后面的代码。在适当的位置合理地使用中间变量或临时变量,会提高效率,增强代码的可读性,但是,不加限制地使用,则会降低代码的可读性,同时也会带来更多的风险。
对上面的代码稍加修改,并封装成函数,感觉顺眼了很多。
>>> def transpose(arr): result, arr_len = list(), len(arr) for j in range(len(arr[0])): result.append(list()) for i in range(arr_len): result[-1].append(arr[i][j]) return result
>>> transpose([[1,2,3], [4,5,6], [7,8,9]])[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
在我收到的答案中,大约有70%和修改后的这段代码类似。不过,这段代码看起来还是有点啰嗦,不够简洁。如果使用列表推导式,则可以在一行之内完成转置。
>>> def transpose(arr): return [[arr[i][j] for i in range(len(arr))] for j in range(len(arr[0]))]
>>> transpose([[1,2,3], [4,5,6], [7,8,9]])[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
使用列表推导式,可以让代码更加紧凑,但会降低可读性,因此应限制使用。在所有收集到的答案中,有几位同学使用了列表推导式,还有两位同学使用了 NumPy 的数组转置。遗憾的是,没有一位同学写出下面这个我认为的最佳答案。
>>> def transpose(arr): return list(zip(*arr))
>>> transpose([[1,2,3], [4,5,6], [7,8,9]])[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
这个答案,用到了内置函数 zip()和一颗星(*)解包魔法,代码简洁高效。想要写出这样经典的答案,有一个前提条件就是对 Python 的内置函数能够信手拈来。Python 内置了七十多个常用函数,配合不同的参数,可以实现非常精妙的功能。比如,从包含重复元素的列表中找出重复次数最多的元素,可以用一行代码高效实现。
>>> arr = [7,3,5,3,6,7,3,5,6,3,5]>>> max(set(arr), key=lambda x:arr.count(x))3
最后,总结一下写出简洁优美的 Python 代码的三条秘诀:
秘诀第 1 条:合理使用中间变量或临时变量
秘诀第 2 条:适度使用列表推导式等语法特性
秘诀第 3 条:尽量使用Python的内置函数
☞达“超人”水平?强化学习得这么用!☞“面向对象就是一个错误!”☞乐视视频 App 图标改为“欠 122 亿”,网友:我在别家分红包,却在你家随份子!
☞30 行代码实现蚂蚁森林自动“偷”能量