Interesting Python

前言

之前曾经因为课程原因学了一段时间 Python,上个月开始实习,重拾这门语言。这次不再是看一些入门教程浅尝则止,有了些新的体会。以下仅记录下这一个月的学习中遇到的一些有趣的点及小小的感悟。

一致性

当我们带着其他面向对象语言的经验进入 Python 的世界,或许会注意到 len(collection) 而不是 collection.len() 的写法。《流畅的 Python》中提到,“当你进一步理解这种不适感背后的原因之后,会发现这个原因,和它所代表的庞大的设计思想,是形成我们通常说的 “Python 风格”(Pythonic) 的关键。

在这之前,先来了解一下 Python 的特殊函数(这些特殊函数的名字以两个下划线开头,以两个下划线结尾)。特殊函数的存在是为了被 Python 解释器调用的,你自己并不需要调用它们。也就是说没有 my_object.len() 这种写法,而应该使用 len(my_object)。在执行 len(my_object) 的时候,如果 my_object 是一个自定义类的对象,那么 Python 会自己去调用其中由你实现的 __len__ 方法。

简单的说,通过实现特殊方法,自定义数据类型可以表现的跟内置类型一样。作为你的类的用户,他们不必去记住标准操作的各式名称。

列表推导

列表推导是构建列表(list)的快捷方式。

eg. 把一个字符串变成 Unicode 码位的列表。

一个刚接触 Python 的人的写法很可能如下(例 1):

1
2
3
4
symbols = '$%^&*'
codes = []
for symbol in symbols:
codes.append(ord(symbol))

使用列表推导的写法则如下(例 2):

1
2
symbols = '$%^&*'
codes = [ord(symbol) for symbol in symbols]

虽说任何学过一点 Python 的人应该都能看懂例 1,但学会了列表推导的话,例 2其实读起来更方便,因为这段代码的功能从字面上就能轻松地看出来。

元组不仅仅是不可变的列表

很多 Python 的入门教程都把元组称为 ”不可变列表“,但其实元组更强大的作用是用于没有字段名的记录。元组中的每个记录都存放了记录中一个字段的数据,外加这个字段的位置。正是这个位置信息给数据赋予了意义。

1
city, year, pop, chg, area = ('Tokyo', 2003, 32450, 0.66, 8014)

如上,东京市的一些信息:市名、年份、人口、人口变化和面积包含在一个元组中,这些字段的意义与它的位置有关。然后通过元组拆包把元组中的元素分别赋给变量 city、year、pop、chg 和 area。

假如需要给记录中的字段命名,Python 还提供了 namedtuple 函数(具名元组)。

写在后面

Python 中有趣的地方当然不止以上这几点,在这里不再细说。有兴趣的去看一下 Python 的专业书籍(不是一些简单的入门教程)相信会收获更多,也比我这里写的更好。

曾经我只是简单的把编程语言当作一个工具,以为只是学会语法,能够编写出代码实现功能便足以。这次重新学习 Python,了解了一些语言背后的设计思想,不禁反省自己曾经的愚昧。诚然,浅尝则止的方式可能可以应付大部分的工作,但很难想象一个不曾去了解一门语言背后原理的人可以写出优雅的代码。

Lastly, “Life is short, you need Python”.