Стиль, форматирование оператора среза

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?

Ответ 1

Как уже упоминалось, PEP8 явно не упоминает оператор slice в этом формате, но spam[3:5] определенно более распространен, а IMHO более читабельен.

Если pep8 checker - это что-то, что нужно пропустить, пробел перед : будет помечен

[[email protected]]$ pep8  <(echo "spam[3:44]")   # no warnings
[[email protected]]$ pep8  <(echo "spam[3 : 44]")  
/dev/fd/63:1:7: E203 whitespace before ':'

... но только из-за этого предполагается, что : является оператором для определения литерала dict, и перед оператором не должно быть пробела. spam[3: 44] проходит по этой причине, но это просто не кажется правильным.

В этом случае я придерживаюсь spam[3:44].


Вложенные арифметические операции немного сложнее. Из ваших 3 примеров только 2-й проходит проверку PEP8:

[[email protected]]$ pep8 <(echo "spam[ham(66)//3:44+eggs()]")
/dev/fd/63:1:13: E225 missing whitespace around operator

[[email protected]]$ pep8 <(echo "spam[ham(66) // 3:44 + eggs()]")  # OK

[[email protected]]$ 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]

Ответ 2

Я вижу срез, используемый в 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. Я не думаю, что метод no-spaces-around-the- : выглядит в этом случае хорошим:

spam[ham(66) / 3:44 + eggs()]   # looks like it has a time in the middle. Bad.

Если вы хотите, чтобы : выделялся больше, не жертвуйте расстоянием оператора, добавьте дополнительные пробелы в ::

spam[ham(66) / 3  :  44 + eggs()]   # Wow, it easy to read!

Я бы не использовал # 1, потому что мне нравится операторский интервал, а # 2 слишком похож на синтаксис словаря key: value.

Я бы тоже не назвал его оператором. Это специальный синтаксис для построения объекта slice - вы также можете сделать

spam[slice(3, 5)]

Ответ 3

Я согласен с вашим первым примером. Для последнего: PEP 20. Показатели удобочитаемости. Семантически наиболее важная часть выражения сложного среза - это сам оператор среза, он делит выражение на две части, которые должны анализироваться (как человеческим читателем, так и интерпретатором) отдельно. Поэтому моя интуиция заключается в том, что согласованность с PEP 8 должна быть принесена в жертву, чтобы выделить оператор :, т.е. окружая его пробелами, как в примере 3. Вопрос в том, что если пропускать пробелы в пределах двух сторон выражения для повышения удобочитаемости или нет:

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

против.

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

Я нахожу 1. быстрее разбираться.