如果需要在Python中的列表、字典或集合常量中添加或移除项,记住一个窍门:在所有行后面都添加一个逗号。
还不太明白?来看一个示例。假设在代码中有下面这个由名字组成的列表:
>>> names = ['Alice', 'Bob', 'Dilbert']
在修改这个名字列表时,通过git diff查看改动可能有点不方便。大多数源码控制系统都是基于行的,因此无法标出同一行中的多个改动。
一个快速改进是根据编码规范,将列表、字典或集合常量分割成多行,如下所示:
>>> names = [
... 'Alice',
... 'Bob',
... 'Dilbert'
... ]
这样每项独占一行,因此可以清楚地从源码控制系统的diff中看出哪里进行了添加、删除和修改操作。虽然只是一个小改动,但我发现这有助于避免很多愚蠢的错误,也让团队成员能够更方便地审阅我的代码改动。
但现在依然有两个编辑情形会导致混乱,即在列表末尾添加或移除内容时,还需要手动调整逗号来保持格式的一致性。
比如需要向列表中添加一个名字Jane
,则需要在Dilbert
这一行的末尾添加一个逗号来避免一个讨厌的错误:
>>> names = [
... 'Alice',
... 'Bob',
... 'Dilbert' # <- 缺失逗号!
... 'Jane'
]
在查看这个列表的内容时,请做好心理准备:
>>> names
['Alice', 'Bob', 'DilbertJane']
可以看到,Python将字符串Dilbert
和Jane
合并成了DilbertJane
。这称为字符串字面值拼接,是文档中有记录的刻意行为。这种行为可能会在程序中引入令人难以琢磨的bug:
以空白符分隔多个相连的字符串或byte字面值,即使它们各自使用不同的引号,也会执行拼接操作。
详见Python文档:“String literal concatenation”。
在某些情况下,字符串字面值拼接是一个有用的特性。例如,在跨越多行的长字符串中可以省去反斜杠:
my_str = ('This is a super long string constant '
'spread out across multiple lines. '
'And look, no backslash characters needed!')
但另一方面,这个特性有时又会成为负担。那么如何解决这个问题呢?
在Dilbert
后添加缺失的逗号就能避免两个字符串合并了:
>>> names = [
... 'Alice',
... 'Bob',
... 'Dilbert',
... 'Jane'
]
现在回到原来的问题。为了向列表添加一个新名字,需要修改两行代码。这同样让开发人员很难从git diff看出到底做了什么改动:到底是添加了一个新名字,还是修改了Dilbert这个名字?
幸运的是Python语法留有余地,让我们可以一劳永逸地解决这个逗号放置问题。只要遵循一种能够避免这个问题的编码风格即可,下面来看具体方法。
在Python中,可以在列表、字典和集合常量中的每一项后面都放置一个逗号,包括最后一项。因此只要记住在每一行末尾都加上一个逗号,就可以避免逗号放置问题。
下面是示例的最终版:
>>> names = [
... 'Alice',
... 'Bob',
... 'Dilbert',
... ]
看到Dilbert
后面的那个逗号了吗?现在能方便地添加或移除新的项,无须再修改逗号了。这不仅让各行代码保持一致,而且源码控制系统生成的diff清晰整洁,让代码审阅者心情愉悦。看到没,有时魔法就藏在这些细微之处。
关键要点
-
合理的格式化及逗号放置能让列表、字典和集合常量更容易维护。
-
Python的字符串字面值拼接特性既可能带来帮助,也可能引入难以发现的bug。