В каких руководящих принципах PEP 8 вы игнорируете, и к какому из них вы придерживаетесь?
На протяжении многих лет, чем больше питонов я пишу, тем больше я соглашаюсь с большинством рекомендаций, хотя я последовательно и намеренно ломаю некоторые по своим собственным причинам.
Мне было бы интересно узнать, что в PEP 8 (или другие PEP тоже могут быть) люди религиозно придерживаются и почему и что люди находят неудобными или неадекватными.
В моем случае (и на работе вообще) есть только несколько вещей, от которых мы отклоняемся:
-
Подчеркнуть отдельные имена нижнего регистра, я могу увидеть его, так как он будет непременно согласован, но мы склонны использовать lowerCamelCase, даже если он иногда вводит некоторые несоответствия (например, частично или неправильно заглавные аббревиатуры и следующие слова, которые часто сводятся к звонкам). В основном из-за того, что почти все API-интерфейсы мы обычно используем, используйте camelCase (некоторые верхние, некоторые ниже), и потому по какой-то причине мне становится легче читать и, как правило, резервировать символы подчеркивания как разделительные токены или предписанные манипуляции/затенения.
-
Я все еще не могу понять, как PEP предписывает внутренние объекты. new и init Я обычно ухожу прямо под классом без пустых строк, так как я всегда хочу их прочитать прямо там с именем класса и args, методами, которые способствуют одинаковой функциональности в классе (скажем, init, get и set из того же атрибута или набора атрибутов). Я разделяю только одно пространство, и мне нравится три пробела между классами, а два между методами, которые я бы не мысленно не суммировал на карте этого объекта.
Это опять же чисто для визуального воздействия и удобочитаемости кода. Я нахожу это очень компактное содержимое внутри управления потоком, и этот вид промежутка между методами и объектами неизменно приводит мой взгляд именно туда, где я хочу, чтобы он продолжал повторное чтение через несколько месяцев после того, как код был припаркован. Он также хорошо реагирует на складывание в моих редакторах по выбору.
-
Некоторые вещи вместо этого я придерживаюсь, которые приводят меня в орехи, когда я читаю написанное иначе, - это вкладки вместо пробелов (особенно когда некоторые редакторы в приложении, которые мы используем, на самом деле не имеют функциональных возможностей для замены вкладок, что значительно способствует загрязнение в кодовой базе на этапе прототипирования).
-
Порядок вещей, таких как импорт, и то, что импортирует, глобалы и т.д. Это действительно отбрасывает меня в файлах с большим объемом импорта, когда они перемешаны или вышли из строя.
-
Пробелы в операторах, особенно когда люди используют вкладки И пытаются выровнять операции присваивания между строками с разной длиной в именах переменных (и, похоже, нет способа убедить тех, кто делает это, что excel ищет кусок кода НЕ опрятно;)).
-
И пробелы внутри блока управления, особенно когда я вижу, по-видимому, случайное расстояние в одном блоке управления потоком, а затем аналогичные количества интервалов, используемых в объекте для методов. Я вынужден их редактировать, прежде чем я даже начну читать проклятую вещь.
Итак, это мои и аргументы за мои "нарушения" ОПТОСОЗ (некоторые разделяли, некоторые нахмурились коллегами). Мне было бы очень интересно узнать, что делают другие питонисты и не делают в этом отношении.
Ответы
Ответ 1
Часть "79 символов в строке" - это нонсенс. В их собственном примере показано, как при чтении кода становится нечитаемым:
class Rectangle(Blob):
def __init__(self, width, height,
color='black', emphasis=None, highlight=0):
if width == 0 and height == 0 and \
color == 'red' and emphasis == 'strong' or \
highlight > 100:
raise ValueError("sorry, you lose")
if width == 0 and height == 0 and (color == 'red' or
emphasis is None):
raise ValueError("I don't think so -- values are %s, %s" %
(width, height))
Blob.__init__(self, width, height,
color, emphasis, highlight)
Это похоже на попытку прочитать новость, написанную как это.
Терминалы с 80 колонками уже более десяти лет не являются серьезной средой разработки. Когда мне нужно редактировать из искалеченной среды 80x25 в крайнем случае, обертка редактора - это небольшое неудобство; Я не собираюсь калечить свой код во время нормальной разработки, чтобы избежать этого.
120 обтекание колонн отлично подходит для современного развития, и у меня нет проблем с 140. Это руководство устарело, и после него получается уродливый, трудно читаемый код.
Ответ 2
PEP8 говорит, что следует избегать "более одного пробела вокруг оператора присваивания (или другого) для выравнивания его с другим" и "никогда не использовать более одного пробела" вокруг математических операторов, но я не следую этому.
Я часто добавляю "посторонние пробелы", когда соседние строки связаны или очень похожи, но не совсем так:
search_start = (f - f_1/3) * n/fs
search_stop = (f + f_1/3) * n/fs
b_lpf, a_lpf = filter(N, 2*pi*fc, 'low', analog=True)
b_hpf, a_hpf = filter(N, 2*pi*fc, 'high', analog=True)
p[x > 1] = np.cosh(order * np.arccosh( x[x > 1]))
p[x < -1] = (1 - 2 * (order % 2)) * np.cosh(order * np.arccosh(-x[x < -1]))
b0 = (1 + cos(w0))/2
b1 = -(1 + cos(w0))
Точно так же раздражает, что я получаю предупреждения стиля кода для массивов чисел, отформатированных таким образом, чтобы они читались так, как будто они обычно форматируются самой библиотекой:
a = array([[-0.198, 0.248, -1.17 , -0.629, 1.378],
[-1.315, 0.947, -0.736, -1.388, 0.389],
[ 0.241, -0.98 , 0.535, 0.951, 1.143],
[-0.601, 1.286, -0.947, 0.037, -0.864],
[ 0.178, -0.289, -1.037, -1.453, -0.369]])
PEP8 предпочел бы отформатировать его так, по-видимому, потому что у нас никогда не будет лишних пробелов перед запятыми или после скобок, даже если это улучшает удобочитаемость:
a = array([[-0.198, 0.248, -1.17, -0.629, 1.378],
[-1.315, 0.947, -0.736, -1.388, 0.389],
[0.241, -0.98, 0.535, 0.951, 1.143],
[-0.601, 1.286, -0.947, 0.037, -0.864],
[0.178, -0.289, -1.037, -1.453, -0.369]])
Ответ 3
PEP8 говорит
Обратите внимание, что наиболее важно то, что "" ", который заканчивает многострочную строку документации, должно находиться на отдельной строке, и предпочтительно перед ней должна стоять пустая строка, например:
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""
Я нахожу это довольно странным, поскольку он просто "посторонний пробел" и трактует открывающие цитаты иначе, чем закрывающие, без видимой причины.
Обоснование дано в PEP 257:
BDFL рекомендует вставлять пустую строку между последним абзацем в многострочном документировании и его заключительными кавычками, помещая закрывающие кавычки в строку самостоятельно. Таким образом, команда Emacs 'fill-абзац' может быть использована для него.
Emacs, правда? Каждый должен делать странные вещи, чтобы удовлетворить особенности конкретной команды в определенном инструменте редактирования?
Я также думаю, что странно помещать начало строки документации в ту же строку, что и кавычки (не обязательно, но рекомендуется), настаивая на том, чтобы заключительные кавычки были на отдельной строке. Я думаю, что это более логично и должно использоваться как для однострочных, так и для многострочных строк документации:
def foobang(bizbaz, plotz=None):
"""
Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""
if plotz is not None:
...
Обновление: жирная часть была удалена, и теперь она просто говорит: "Поместить заключительные кавычки в строку самостоятельно", и что "итоговая строка может быть в той же строке, что и начальные кавычки, или в следующей строке".
Ответ 4
Я не согласен с этим:
- Imports should usually be on separate lines, e.g.:
Yes: import os
import sys
No: import sys, os
Я всегда пишу простой импорт вместе. Я не вижу никакого преимущества в написании их всех на отдельных строках: все, что он делает, это добавить раздувание вверху каждого исходного файла и сделать что-то кратким и легким вписать в что-то, что граничит с шаблоном, например. что-то, что так многословно, начинает заманчиво копировать и вставлять из других файлов.
Это мгновенно читаемо и понятно:
import sys, os, time, gc, inspect, math, doctest
Он короткий, легко снимается и легко добавляется. Я использую несколько операторов import
, если их слишком много в одной строке, или мне нужен импорт from
.
Я также обычно сохраняю стандартный импорт библиотек отдельно от импорта моих собственных модулей и других библиотек, что согласуется с концепцией группировки PEP8.
Ответ 5
Стандарты имеют решающее значение, и PEP 8 - это очень хороший стиль, которым я настаиваю. Единственным ориентиром, с которым я не согласен, является расстояние между математическими операторами. Например, PEP8 настаивает на следующих расстояниях
Without PEP8 With PEP8
----------------------------------------------------------------
y = sqrt(x**2 + y**2) y = sqrt(x ** 2 + y ** 2)
a*x**3 + b*x**2 + c*x + d a * x ** 3 + b * x ** 2 + c * x + d
10**(a*x + b) 10 ** (a * x + b)
F = V/(sqrt(g*h) + epsilon) F = V / (sqrt(g * h) + epsilon)
a*cos(nx/pi) + b*sin(nx/pi) a * cos(nx / pi) + b * sin(nx / pi)
Я пытаюсь соответствовать, но это та область, в которой я борюсь.
Кто-нибудь еще чувствует, что интервал PEP8 затрудняет чтение математики?
Update:
PEP8 был исправлен, чтобы рекомендовать форматирование на слева, не поощряя форматирование справа:
Да:
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
<Не p > Нет:
i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
Ответ 6
В моих правилах стиля компании вызывается призыв, а не пробелы. PEP 8 намекает, что места предпочтительнее, но мы нашли обратное. Мне нравится видеть код с отступом 4 'пробелов' в VIM, сотрудник предпочитает 8 'пробелов' в Emacs. Использование вкладок позволяет нам настроить наших редакторов на отображение кода по своему усмотрению.
Обратите внимание, что в других языках на языке C наложение фактически является просто форматированием, но в Python отступ является синтаксисом, поэтому мы чувствуем, что indentation level 2
должно быть представлено 2
чего-либо (т.е. вкладки) не 4
или 8
чего-либо (т.е. пробелов).
Выбор символа отступа - это, вероятно, оригинальная война с огнем святого пламени (даже до вспышек VIM/Emacs), поэтому я ожидаю, что вы затушевываетесь, чтобы выразить свое мнение по этому вопросу!
Ответ 7
Я всегда использую 4 пробела, я стараюсь использовать не более 79 символов в строке, а иногда невозможно.
Я также использовал импорт, как "import sys, os" в прошлом.
В общем, я стараюсь придерживаться PEP 8.
Изменить: также использовать:
def foobar():
"""
foobar
"""
для документации
Ответ 8
Многострочные условные обозначения и т.д.: PEP-8 явно говорит, что он разбивается после двоичного оператора, а не перед ним. Боюсь, что я не вижу этого. Для меня гораздо больше смысла ломаться до условного, так что в завернутых/продолженных линиях каждая подстрока начинается с условного:
if (condition1 \
or condition2 \
or condition3):
do_something()
Как можно видеть, я также хотел бы добавить дополнительный отступ для sublines, так что они визуально смещены от блока ниже. PEP-8 ничего не говорит об этом (не так ли?), Но в примерах есть подстроки, выровняющиеся с открывающимися круглыми скобками.
Ответ 9
PEP 8 говорит:
Да:
x = 1
y = 2
long_variable = 3
<Не p > Нет:
x = 1
y = 2
long_variable = 3
Я обычно следую за ним, но иногда я использую другой вариант для лучшей читаемости:
x = 1
y = 2
long_variable = 3
Ответ 10
"Я допускаю нарушение" - это "если"
PEP8 не говорит о множественном утверждении в одной строке, поэтому, если мы должны это сделать:
if cond:
actions
...
Но когда есть только одно действие, я предпочитаю все в одной строке,
например Я предпочитаю:
if a == 0: b = 0
чем:
if a == 0:
b = 0
Ответ 11
"Проблема" в PEP 8 состоит в том, что он затрагивает области личных предпочтений, которые вызывают у большинства программистов довольно сильные эмоции.
Лично для меня постоянные проблемы были с подчеркиванием и верблюдом в CamelCase. Я также вижу смысл во многих других ответах здесь, и иногда я намеренно нарушаю PEP 8, потому что в этом конкретном случае это просто "имеет смысл".
В моей карьере программиста на Python был момент, когда я просто сдался и повернулся к (используя) PEP 8. Для большинства элементов это было относительно легко, поэтому в настоящее время единственной серьезной проблемой, с которой я сталкиваюсь, является выравнивание столбцов. Этот просто слишком грязный, чтобы повиноваться (хотя я ненавижу в любом случае). В любом случае, из-за того, что я "сдался", мой код стал гораздо более читаемым для моих коллег - и - что удивительно: даже для меня (за исключением выравнивания столбцов, вещь: p).
Я также должен признать, что PEP 8 сделал для самого Python: между 2.x (несовместимым) и 3.x (совместимым), мне гораздо легче "всегда знать", каким будет конкретное имя функции. "Батареи" Python теперь сортируются намного приятнее.
Ответ 12
Когда я пишу крошечные скрипты, я часто просто использую два пробела.
Я всегда использую тот же шаблон для docstrings:
def function():
"""
Even if it a single line.
"""
Ответ 13
Я использую pylint, http://pypi.python.org/pypi/pylint, это отличный инструмент для того, чтобы ваш код был чистым и читаемым для вас и других разработчиков, ваш код.
Я не затрагиваю все те темы, которые вы сказали, но это очень полезно.
У вас могут быть такие отчеты, как этот:
[email protected]:~/src/fcl/cltools$ pylint numbertoletters.py
No config file found, using default configuration
************* Module numbertoletters
C: 1: Missing docstring
C: 56:es_numero: Missing docstring
C: 56:es_numero: Invalid name "s" (should match [a-z_][a-z0-9_]{2,30}$)
C: 56:es_numero: Invalid name "s" (should match [a-z_][a-z0-9_]{2,30}$)
C: 69:convertnumbertoletters: Empty docstring
C: 90:convertnumbertoletters: Operator not preceded by a space
numero='%(numero)09d' % {'numero' : int(parte_entera)}
^
C: 92:convertnumbertoletters: Comma not followed by a space
for i in [0,3,6]:
^^
W: 69:convertnumbertoletters: Unused argument 'languaje'
C:108:unidades: Empty docstring
C:108:unidades: Invalid name "x" (should match [a-z_][a-z0-9_]{2,30}$)
C:108:unidades: Invalid name "x" (should match [a-z_][a-z0-9_]{2,30}$)
C:112:unidades: Invalid name "u" (should match [a-z_][a-z0-9_]{2,30}$)
C:118:teens: Empty docstring
C:118:teens: Invalid name "x" (should match [a-z_][a-z0-9_]{2,30}$)
C:118:teens: Invalid name "x" (should match [a-z_][a-z0-9_]{2,30}$)
C:122:teens: Invalid name "t" (should match [a-z_][a-z0-9_]{2,30}$)
C:127:tens: Empty docstring
C:127:tens: Invalid name "x" (should match [a-z_][a-z0-9_]{2,30}$)
C:127:tens: Invalid name "x" (should match [a-z_][a-z0-9_]{2,30}$)
C:131:tens: Invalid name "t" (should match [a-z_][a-z0-9_]{2,30}$)
C:137:tercia: Empty docstring
C:141:tercia: Operator not preceded by a space
numero='%(numero)03d' % {'numero' : int(num)}
^
C:143:tercia: Invalid name "a" (should match [a-z_][a-z0-9_]{2,30}$)
C:144:tercia: Invalid name "b" (should match [a-z_][a-z0-9_]{2,30}$)
C:145:tercia: Invalid name "c" (should match [a-z_][a-z0-9_]{2,30}$)
C:163:tercia: Operator not followed by a space
resultado ='veinti '+unidades(c)
^
C:165:tercia: Operator not followed by a space
elif b >=3 and b <= 9:
^^
C:178:tercia: Operator not followed by a space
resultado ='ciento '+unidades(c)
^
C:192:tercia: Operator not followed by a space
resultado ='ciento veinti '+unidades(c)
^
C:204:tercia: Operator not preceded by a space
prefix='quinientos '
^
C:206:tercia: Operator not preceded by a space
prefix='setecientos '
^
C:208:tercia: Operator not preceded by a space
prefix='novecientos '
^
C:210:tercia: Operator not preceded by a space
prefix=unidades(a)+'cientos '
^
R:137:tercia: Too many return statements (23/6)
R:137:tercia: Too many branches (41/12)
R:137:tercia: Too many statements (73/50)
Report
======
141 statements analysed.
Raw metrics
-----------
+----------+-------+------+---------+-----------+
|type |number |% |previous |difference |
+==========+=======+======+=========+===========+
|code |144 |68.25 |NC |NC |
+----------+-------+------+---------+-----------+
|docstring |5 |2.37 |NC |NC |
+----------+-------+------+---------+-----------+
|comment |57 |27.01 |NC |NC |
+----------+-------+------+---------+-----------+
|empty |5 |2.37 |NC |NC |
+----------+-------+------+---------+-----------+
Statistics by type
------------------
+---------+-------+-----------+-----------+------------+---------+
|type |number |old number |difference |%documented |%badname |
+=========+=======+===========+===========+============+=========+
|module |1 |NC |NC |0.00 |0.00 |
+---------+-------+-----------+-----------+------------+---------+
|class |0 |NC |NC |0 |0 |
+---------+-------+-----------+-----------+------------+---------+
|method |0 |NC |NC |0 |0 |
+---------+-------+-----------+-----------+------------+---------+
|function |6 |NC |NC |0.00 |0.00 |
+---------+-------+-----------+-----------+------------+---------+
Duplication
-----------
+-------------------------+------+---------+-----------+
| |now |previous |difference |
+=========================+======+=========+===========+
|nb duplicated lines |0 |NC |NC |
+-------------------------+------+---------+-----------+
|percent duplicated lines |0.000 |NC |NC |
+-------------------------+------+---------+-----------+
Messages by category
--------------------
+-----------+-------+---------+-----------+
|type |number |previous |difference |
+===========+=======+=========+===========+
|convention |32 |NC |NC |
+-----------+-------+---------+-----------+
|refactor |3 |NC |NC |
+-----------+-------+---------+-----------+
|warning |1 |NC |NC |
+-----------+-------+---------+-----------+
|error |0 |NC |NC |
+-----------+-------+---------+-----------+
Messages
--------
+-----------+------------+
|message id |occurrences |
+===========+============+
|C0103 |14 |
+-----------+------------+
|C0322 |6 |
+-----------+------------+
|C0112 |5 |
+-----------+------------+
|C0323 |4 |
+-----------+------------+
|C0111 |2 |
+-----------+------------+
|W0613 |1 |
+-----------+------------+
|R0915 |1 |
+-----------+------------+
|R0912 |1 |
+-----------+------------+
|R0911 |1 |
+-----------+------------+
|C0324 |1 |
+-----------+------------+
Global evaluation
-----------------
Your code has been rated at 7.45/10
I hope it helps.
Я настоятельно рекомендую использовать pylint для оценки вашего кода и придерживаться стандартного способа программирования, особенно в сообществе разработчиков. =)
Надеюсь, это поможет.
Ответ 14
python-mode.el, https://launchpad.net/python-mode
тем временем позволяет настраивать стиль:
M-x настраивать переменную RET py-docstring-style RET
Значение по умолчанию - pep-257-nn
Реализованные стили: DJANGO, ONETWO, PEP-257, PEP-257-NN,
SYMMETRIC и NIL.
Значение NIL не будет заботиться о котировках
положение и будет обрабатывать докстры, нормальные строки, любые другие
значение может привести к одному из следующих типов docstring:
DJANGO:
"""
Process foo, return bar.
"""
"""
Process foo, return bar.
If processing fails throw ProcessingError.
"""
Onetwo:
"""Process foo, return bar."""
"""
Process foo, return bar.
If processing fails throw ProcessingError.
"""
PEP-257:
"""Process foo, return bar."""
"""Process foo, return bar.
If processing fails throw ProcessingError.
"""
PEP-257-NN:
"""Process foo, return bar."""
"""Process foo, return bar.
If processing fails throw ProcessingError.
"""
SYMMETRIC:
"""Process foo, return bar."""
"""
Process foo, return bar.
If processing fails throw ProcessingError.
"""