样式:格式化切片操作符

14 投票
3 回答
4588 浏览
提问于 2025-04-17 06:06

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 个回答

3

我同意你提到的第一个例子。至于后一个例子,可以参考一下PEP 20。可读性很重要。在你复杂的切片表达式中,最重要的部分就是切片操作符,它把这个表达式分成了两部分,这两部分应该被人和解释器分别解析。因此,我觉得为了突出:操作符,可能需要牺牲一下与PEP 8的一致性,比如像第三个例子那样,在操作符周围加上空格。问题是,去掉表达式两边的空格是否真的能提高可读性呢:

1. spam[ham(66)/3 : 44+eggs()]

2. spam[ham(66) / 3 : 44 + eggs()]

我觉得第一个例子更容易理解。

4

我看到在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)]
13

正如你提到的,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]

撰写回答