стиль, форматирующий оператор среза

#python #coding-style

#python #стиль кодирования

Вопрос:

В PEP 8 оператор среза не упоминается. Насколько я понимаю, в отличие от других операторов, он не должен быть окружен пробелом

 spam[3:5]   # OK
spam[3 : 5] # NOT OK
  

Выполняется ли это при использовании сложных выражений, то есть какой из них считается лучшим стилем

 1. спам [ветчина(66)//3:44 яйца()]
 2. спам[ветчина(66) // 3: 44   яйца()]
 3. спам [ветчина(66) // 3 : 44   яйца()]
 4. что-то еще?

Ответ №1:

Как вы уже упоминали, PEP8 явно не упоминает оператор среза в этом формате, но spam[3:5] определенно более распространен и, ИМХО, более удобочитаем.

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

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

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

Исходя из этого, я бы придерживался spam[3:44] .


Вложенные арифметические операции немного сложнее. Из ваших 3 примеров только 2-й проходит проверку 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]
  

Ответ №2:

Я вижу нарезку, используемую в PEP8:

 - Используйте ".startswith() и ".endswith() вместо среза строки для проверки 
 для префиксов или суффиксов.

 startswith() и endswith() более чистые и менее подвержены ошибкам. Для 
 пример:

 Да: если foo.startswith('bar'):

 Нет: если 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)]
  

Ответ №3:

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

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

против.

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

Я нахожу 1. более быстрый синтаксический анализ.