Чи слід реально використовувати всі великі регістри для своїх констант?


34

Я насамперед програміст Python, який використовує пілінт для зв’язування вихідного коду. Я в змозі усунути всі попередження, крім одного: Неправильне ім'я для константи. Зміна імені на всі шапки виправляє це, але чи я дійсно повинен це робити? Якщо я це роблю, я вважаю, що мій код виглядає некрасиво, оскільки більшість змінних є постійними (відповідно до pylint).


2
Якщо більшість ваших змінних є константами рівня модуля, ви, ймовірно, робите щось незвичне. Більшість з них повинні жити всередині функцій.
RemcoGerlich

1
чи можете ви показати нам зразок вашого коду, який пілінт вважає константами?
Вінстон Еверт

@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
Дуже не погоджуюся, я думаю, що є багато хороших пітонічних причин використовувати змінні рівня модулів. Я думаю, що ця порада є лише артефактом неправильного читання PEP8 пілінта, і якщо припустити, що зворотне значення "константи повинні бути рівнем модуля" також має бути правдивим.
MetricSystem

21

Так. Згідно з правилом PEP8 щодо констант :

Константи зазвичай визначаються на рівні модуля і пишуться великими літерами з підкресленнями слів. Приклади включають MAX_OVERFLOWта TOTAL.

Довга версія:

У спільноті Python (як і у багатьох інших спільнотах) існують конвенції про те, як писати код. Це відрізняється від робочого коду : навіть якщо ви пишете константи всіма малими літерами, ваш код все одно працює.

Але є консенсус громади (як це зафіксовано в PEP8), який "застосовується" за допомогою таких інструментів, як пілінт . Якщо ви програмуєте на своє власне щастя, ви можете нехтувати натяками, які дає вам полінт. Якщо ви хочете відкритого обміну з громадою, він же "хтось, крім мене, повинен використовувати мій код", ви повинні підготувати свій код відповідно до PEP8.


7
З іншого боку, це цілком можливо, pylintщоб помилитися. Python не пропонує способу відрізнити константу від змінної, окрім того, що очікується, що константа завжди матиме однакове значення. pylintпередбачає , що всі , що тільки одноразово і не коли - або зміна є постійним, але якщо це не призначене , щоб бути постійним, це може бути просто артефакт реалізації. І конкретно, код, що надається в коментарі до питання, має значення, які будуть різними на кожному етапі, тому не слід вважати константами, навіть якщо пілінт вважає, що вони є.
Жуль

@Jules Я б назвав змінні, встановлені один раз і змінюються під час виконання, ніколи не є постійними, тому існує у багатьох мовах (наприклад, у JS) constключове слово. Незважаючи на те, початкове значення відрізняється, крім , можливо PI.
Томас Джунк

1
Я б розрізняв незмінну змінну (тобто те, що встановлюється під час виконання та не змінюється) та константою (тобто те, що є однаковим у кожному запуску програми, і якщо мова надає можливість зробити це, можна було б обчислити під час компіляції ) ... справа в тому, що оскільки немає будь-якого способу вказувати відмінність на python, 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починає грати, це допомагає пам’ятати, що константи з усіма великими кришками, як правило, насправді не витримують платонічних ідеалів , а параметри програми. Немає нічого істинно постійного в тому 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.