Должен ли я действительно использовать все прописные буквы для моих констант?

34

Я в основном программист на Python, который использует pylint для слияния исходного кода. Я могу удалить все предупреждения, кроме одного: Неверное имя для константы. Изменение названия на все заглавные буквы исправляет это, но действительно ли я должен это делать? Если я сделаю это, я обнаружу, что мой код выглядит безобразно, так как большинство переменных являются постоянными (в соответствии с Pylint).

Абхишек Кумар
источник
2
Если большинство ваших переменных являются константами уровня модуля, вы, вероятно, делаете что-то необычное. Большинство из них должны жить внутри функций.
RemcoGerlich
1
Можете ли вы показать нам пример кода, который Pylint считает постоянными?
Уинстон Эверт
@WinstonEwertNOTES_DIRECTORY = argv[1] chdir(NOTES_DIRECTORY) FILES = glob('*.txt') RAND_FILE = choice(FILES) with open(RAND_FILE) as notes_file: POINTS = notes_file.readlines() RAND_POINT = choice(POINTS)
Абхишек Кумар
@AbhishekKumar, ваш код в функции или на верхнем уровне?
Уинстон Эверт
@WinstonEwert На верхнем уровне и после следования инструкциям PyLint.
Абхишек Кумар

Ответы:

33

Вы, вероятно, пишете такой код:

notes_director = argv[1]
chdir(notes_director)
files = glob('*.txt')
rand_file = choice(files)
with open(rand_file) as notes_file: 
    points = notes_file.readlines() 
    rand_point = choice(points)

Вы должны переместить этот код в функцию:

def main():
    notes_director = argv[1]
    chdir(notes_director)
    files = glob('*.txt')
    rand_file = choice(files)
    with open(rand_file) as notes_file: 
        points = notes_file.readlines() 
        rand_point = choice(points)

# actually call the main function    
main()

Pylint предполагает, что код, который фактически выполняет эту работу, будет внутри функции. Поскольку этот код находится на верхнем уровне кода, а не внутри функции, он запутывается.

Вообще говоря, лучше работать внутри функции, а не на верхнем уровне. Это позволяет вам лучше организовать то, что вы делаете, и облегчает его повторное использование. На самом деле у вас должен быть только код, выполняющий алгоритм вне функции в быстром и грязном скрипте.

Уинстон Эверт
источник
1
Сильно не согласен, я думаю, что есть много веских причин Pythonic для использования переменных уровня модуля. Я думаю, что этот совет является просто артефактом неправильного прочтения PIL8 PILINT, и предположение о том, что «константы должны быть на уровне модуля» также должно быть верным.
MetricSystem
21

Да. Согласно правилу PEP8s о константах :

Константы обычно определяются на уровне модуля и пишутся заглавными буквами с подчеркиванием, разделяющим слова. Примеры включают MAX_OVERFLOWи TOTAL.

Длинная версия:

В сообществе Python (как и во многих других сообществах) существуют соглашения о том, как писать код. Это отличается от рабочего кода : даже если вы пишете свои константы в нижнем регистре, ваш код все еще работает.

Но существует консенсус сообщества (как задокументировано в PEP8), который "навязывается" такими инструментами, как Pylint . Если вы программируете для собственного счастья, вы можете игнорировать подсказки, которые дает вам Pylint. Если вы хотите открытого обмена с сообществом, то есть «кто-то кроме меня должен использовать мой код», вы должны подготовить свой код в соответствии с PEP8.

Томас Джанк
источник
7
С другой стороны, вполне возможно pylintошибиться. Python не предоставляет способ отличить константу от переменной, кроме того, что константа всегда должна иметь одно и то же значение. pylintпредполагает , что все , что только однократно и не когда - либо изменение является постоянным, но если это не предназначено , чтобы быть постоянным, это может быть просто артефакт реализации. И, в частности, код, приведенный в комментарии к вопросу, имеет значения, которые будут отличаться при каждом запуске, поэтому его не следует считать константой, даже если Pylint считает, что это так.
Жюль
@Jules Я бы назвал переменные, заданные один раз и изменяющиеся во время выполнения, никогда больше не константой, поэтому во многих языках (например, в JS) существует constключевое слово. Хотя начальное значение отличается, кроме, может быть PI.
Томас Джанк
1
Я бы различал неизменяемую переменную (то есть то, что установлено во время выполнения и не изменено) и константу (то есть то, что одинаково при каждом запуске программы, и если язык предоставляет возможность сделать это, он может быть вычислен во время компиляции ) ... суть в том, что, поскольку отсутствует какой-либо способ указать различие для python, pylintподразумевается последнее, даже если первое имеет место.
Жюль
Pylint определенно ошибается в том смысле, что он читает «константы должны быть уровня модуля» и предполагает обратное «уровень модуля должен быть константами». Но поскольку в остальном это хороший, полезный инструмент, кажется, мы застряли с ним.
MetricSystem
@MetricSystem Какую, по вашему мнению, функцию будет иметь переменная уровня модуля, кроме того, что она является константой? Должно ли оно быть изменчивым?
Томас Джанк
13

PEP8 и норма сообщества Python - это использование ALL_CAPS_CONSTANTS. Это общая визуальная подсказка, используемая десятилетиями в C, Java, Perl, PHP, Python, bash и других языках программирования и средах оболочки. Но на современном интернет-языке ВСЕ КОПИИ ЗНАЧИТ КРИТЬ . И кричать это грубо.

Python, однако, довольно противоречив ALL_CAPS_CONSTANTS. JavaScript может иметь Math.PI, но Python есть math.pi. Нет более узнаваемой или устойчивой константы, чем π. Или рассмотрите sys.version_infoверсию Python, на которой вы работаете. 100% постоянным в течение жизни вашей программы - гораздо больше , чем PORTили MAX_ITERATIONSили другие константы , которые бы определить. Или как насчет sys.maxsize? Максимальное собственное целочисленное значение вашей платформы постоянно не только в течение одного или двух запусков программы, но и в течение срока службы вашего оборудования.

Если эти константы, в том числе такие, как π и e, являются фундаментальными константами вселенной и не будут изменяться в течение всей вечности, - если они могут быть строчными, хорошо ... как и другие константы. Ты можешь выбрать.

Помните, PEP8 - это руководство по стилю. Руководство, а не закон. Руководство часто нарушается даже стандартной библиотекой Python. И ссылаясь на другое основное руководство по Python, PEP20 (он же «Дзен Питона»):

  • Красиво лучше, чем некрасиво
  • Читаемость имеет значение
  • Практичность превосходит чистоту.

На практическом примечании, когда програмы YELLY_CONSTANTи SHOUTY_PARAMETERначинает тереть, это помогает помнить , что все-CAPS константы как правило, не очень прочный платоновские идеалы , но параметры работы программы. Там нет ничего действительно постоянной о PORT, SITENAMEили NUMRUNS, и они не должны управляться как отдельная программа глобалов. Например, их можно поместить в словарь как глобально доступный набор параметров программы:

config = {
    'port': 80,
    'sitename': "Bubba's Blog",
    'numruns': 100,
}

В Python также есть прекрасная возможность передачи параметров ключевых слов, что уменьшает необходимость использования APPARENTLY_ANGRY_GLOBAL_VARIABLES:

def process_data(sitename, port=80, numruns=100):
    ...

process_data("Bubba's Blog")

На практике многие из этих значений будут (или должны быть) считаны из файлов конфигурации, переменных среды ОС, аргументов командной строки или других источников для удовлетворения инверсии принципа / шаблона управления. Но это большая история для другого дня.

Джонатан Юнис
источник
1

Да, это довольно часто встречается в большинстве языков программирования (по крайней мере, тех, которые я использую).

Вы можете обратиться к этой ссылке Google, чтобы поделиться общим стилем между разработчиками одной команды.

Рекомендуется использовать

Type                  |Public          |Internal
Global/Class Constants|CAPS_WITH_UNDER |_CAPS_WITH_UNDER
alain.janinm
источник