样式:格式化切片操作符
PEP 8 并没有提到切片操作符。根据我的理解,和其他操作符不同,切片操作符前后不应该加空格。
spam[3:5] # OK
spam[3 : 5] # NOT OK
在使用复杂表达式时,这种说法是否依然成立?也就是说,哪种写法被认为是更好的风格呢?
1. spam[ham(66)//3:44+eggs()] 2. spam[ham(66) // 3: 44 + eggs()] 3. spam[ham(66) // 3 : 44 + eggs()] 4. something else?
3 个回答
我同意你提到的第一个例子。至于后一个例子,可以参考一下PEP 20。可读性很重要。在你复杂的切片表达式中,最重要的部分就是切片操作符,它把这个表达式分成了两部分,这两部分应该被人和解释器分别解析。因此,我觉得为了突出:
操作符,可能需要牺牲一下与PEP 8的一致性,比如像第三个例子那样,在操作符周围加上空格。问题是,去掉表达式两边的空格是否真的能提高可读性呢:
1. spam[ham(66)/3 : 44+eggs()]
与
2. spam[ham(66) / 3 : 44 + eggs()]
我觉得第一个例子更容易理解。
我看到在PEP8中有提到切片的用法:
- Use ''.startswith() and ''.endswith() instead of string slicing to check for prefixes or suffixes. startswith() and endswith() are cleaner and less error prone. For example: Yes: if foo.startswith('bar'): No: if foo[:3] == 'bar':
我不认为这算是最终的答案,但它支持了你(和我)的理解:
spam[3:5] # OK
在更复杂的情况下,我会选择第3种方法。我觉得在这种情况下,:
周围没有空格的写法看起来不太好:
spam[ham(66) / 3:44 + eggs()] # looks like it has a time in the middle. Bad.
如果你想让:
更显眼,就不要牺牲运算符的空格,而是给:
加上额外的空格:
spam[ham(66) / 3 : 44 + eggs()] # Wow, it's easy to read!
我不会选择第1种,因为我喜欢运算符之间有空格,而第2种看起来太像字典的key: value
语法了。
我也不认为这算是一个运算符。这是一种特殊的语法,用来构造一个slice
对象——你也可以这样做:
spam[slice(3, 5)]
正如你提到的,PEP8并没有明确说明切片操作符的格式,但 spam[3:5]
确实更常见,而且我觉得更容易读懂。
如果参考一下 pep8检查工具,在 :
前面加空格会被标记出来。
[me@home]$ pep8 <(echo "spam[3:44]") # no warnings
[me@home]$ pep8 <(echo "spam[3 : 44]")
/dev/fd/63:1:7: E203 whitespace before ':'
... 但这只是因为它假设 :
是用来定义字典的操作符,而在操作符前面不应该有空格。像 spam[3: 44]
这样的写法就能通过检查,但我觉得这样写不太对。
所以,我会坚持使用 spam[3:44]
。
嵌套的算术运算稍微复杂一些。在你给的三个例子中,只有第二个例子符合PEP8的要求:
[me@home]$ pep8 <(echo "spam[ham(66)//3:44+eggs()]")
/dev/fd/63:1:13: E225 missing whitespace around operator
[me@home]$ pep8 <(echo "spam[ham(66) // 3:44 + eggs()]") # OK
[me@home]$ pep8 <(echo "spam[ham(66) // 3 : 44 + eggs()]")
/dev/fd/63:1:18: E203 whitespace before ':'
不过,我发现以上所有例子一开始看起来都挺难理解的。
为了提高可读性并符合PEP8,我个人会选择:
spam[(ham(66) // 3):(44 + eggs())]
或者对于更复杂的运算:
s_from = ham(66) // 3
s_to = 44 + eggs()
spam[s_from:s_to]