Czy naprawdę powinienem używać wszystkich wielkich liter dla moich stałych?

34

Jestem programistą Python, który przede wszystkim korzysta z pylint do kodowania kodu źródłowego. Jestem w stanie wyeliminować wszystkie ostrzeżenia oprócz jednego: Niepoprawna nazwa stałej. Zmienia nazwę na wszystkie wielkie litery to naprawia, ale czy naprawdę powinienem to zrobić? Jeśli to zrobię, okaże się, że mój kod wygląda brzydko, ponieważ większość zmiennych jest stała (zgodnie z pylintem).

Abhishek Kumar
źródło
2
Jeśli większość zmiennych jest stała na poziomie modułu, prawdopodobnie robisz coś niezwykłego. Większość z nich powinna żyć wewnątrz funkcji.
RemcoGerlich
1
czy możesz nam pokazać próbkę kodu, który według pylint jest stały?
Winston Ewert
@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)
Abhishek Kumar
@AbhishekKumar, czy Twój kod jest w funkcji, czy na najwyższym poziomie?
Winston Ewert,
@WinstonEwert Na najwyższym poziomie i po wykonaniu instrukcji PyLint.
Abhishek Kumar

Odpowiedzi:

33

Prawdopodobnie piszesz taki kod:

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)

Powinieneś przenieść ten kod do funkcji:

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 zakłada, że ​​kod, który faktycznie wykonuje pracę, będzie znajdować się w funkcji. Ponieważ masz ten kod na najwyższym poziomie kodu, a nie wewnątrz funkcji, jest to mylące.

Ogólnie rzecz biorąc, lepszym stylem jest wykonywanie pracy wewnątrz funkcji zamiast na najwyższym poziomie. To pozwala lepiej zorganizować to, co robisz i ułatwia ponowne użycie. Naprawdę powinieneś mieć kod wykonujący algorytm poza funkcją w szybkim i brudnym skrypcie.

Winston Ewert
źródło
1
Zdecydowanie się nie zgadzam, myślę, że istnieje wiele dobrych Pythońskich powodów, aby używać zmiennych na poziomie modułu. Myślę, że ta rada jest jedynie artefaktem pylinta, który źle odczytuje PEP8, i założenie, że odwrotność „stałych powinno być na poziomie modułu”, również powinna być prawdziwa.
MetricSystem
21

Tak. Zgodnie z zasadą PEP8 dotyczącą stałych :

Stałe są zwykle definiowane na poziomie modułu i pisane wielkimi literami z podkreślnikami oddzielającymi słowa. Przykłady obejmują MAX_OVERFLOWi TOTAL.

Długa wersja:

W społeczności Python (podobnie jak w wielu innych społecznościach) istnieją konwencje dotyczące pisania kodu. Różni się to od działającego kodu : nawet jeśli zapisujesz stałe małymi literami, kod nadal działa.

Ale istnieje konsensus społeczny (jak udokumentowano w PEP8), który jest „egzekwowany” za pomocą narzędzi takich jak pylint . Jeśli programujesz dla własnego szczęścia, możesz zaniedbać wskazówki, które daje pylint. Jeśli chcesz otwartej wymiany ze społecznością, czyli »ktoś poza mną, powinien użyć mojego kodu«, powinieneś przygotować swój kod zgodnie z PEP8.

Thomas Junk
źródło
7
Z drugiej strony jest całkowicie możliwe, pylintże się pomylisz. Python nie zapewnia sposobu odróżniania stałej od zmiennej, poza tym, że oczekuje się, że stała będzie zawsze miała tę samą wartość. pylintzakłada, że ​​wszystko, co jest ustawione tylko raz i nigdy się nie zmienia, jest stałą, ale jeśli nie ma być stałą, może to być tylko artefakt implementacji. W szczególności kod podany w komentarzu do pytania ma wartości, które będą się różnić przy każdym uruchomieniu, dlatego nie należy ich uważać za stałe, nawet jeśli pylint tak uważa.
Jules
@Jules Nazywałbym zmienne ustawione raz i zmieniające się w czasie wykonywania nigdy już nie stały, dlatego istnieje w wielu językach (np. W JS) constsłowo kluczowe. Chociaż wartość początkowa jest inna, niż może PI.
Thomas Junk
1
Rozróżniałbym między niezmienną zmienną (tj. Ustawioną w czasie wykonywania i niezmienioną ) a stałą (tj. Czymś, co jest takie samo w każdym uruchomieniu programu, a jeśli język zapewnia taką możliwość, można to obliczyć w czasie kompilacji ) ... chodzi o to, że ponieważ nie ma żadnego sposobu określenia rozróżnienia na python, pylintzakłada się ten drugi, nawet jeśli pierwszy ma miejsce.
Jules
Pylint zdecydowanie się myli, ponieważ odczytuje „stałe powinny być na poziomie modułu” i zakłada, że ​​„poziom modułu powinien być stały”. Ale ponieważ jest to dobre, przydatne narzędzie, wydaje się, że utknęliśmy z nim.
MetricSystem
@MetricSystem jaką - Twoim zdaniem - funkcję miałaby zmienna na poziomie modułu oprócz tego, że jest stała? Czy powinien być zmienny?
Thomas Junk
13

Należy używać norm społeczności PEP8 i Python ALL_CAPS_CONSTANTS. Jest to wspólna wskazówka wizualna, używana od dziesięcioleci w językach C, Java, Perl, PHP, Python, bash i innych językach programowania oraz środowiskach powłoki. Ale w nowoczesnym mowie online WSZYSTKIE KAPTURY SYGNUJĄ SHOUTING . I krzyczenie jest niegrzeczne.

Python jest jednak dość niespójny ALL_CAPS_CONSTANTS. JavaScript może mieć Math.PI, ale Python ma math.pi. Nie ma bardziej rozpoznawalnej lub trwałej stałej niż π. Lub weź pod uwagę sys.version_infowersję Pythona, na której pracujesz. 100% stałe przez cały okres programu - znacznie bardziej niż PORTlub MAX_ITERATIONSlub inne stałe chcesz zdefiniować. A może sys.maxsize? Maksymalna natywna wartość całkowita Twojej platformy jest stała w czasie nie tylko jednego lub dwóch uruchomień programu, ale także żywotności sprzętu.

Jeśli te stałe - w tym niektórzy lubią Õ i E, które są podstawowymi stałymi wszechświata i nie będzie zmieniać się całą wieczność - jeśli oni mogą być małymi literami, dobrze ... więc można inne stałe. Możesz wybrać.

Pamiętaj, PEP8 to przewodnik po stylu. Wytyczna, a nie prawo. Wytyczne często sprzeczne nawet ze standardową biblioteką Pythona. Powołując się na inną podstawową wytyczną Python, PEP20 (alias „The Zen of Python”):

  • Piękne jest lepsze niż brzydkie
  • Liczy się czytelność
  • Praktyczność bije czystość.

Praktycznie rzecz biorąc, kiedy program YELLY_CONSTANTi SHOUTY_PARAMETERzaczyna się sprawdzać, pomaga pamiętać, że stałe wielkich liter na ogół nie są tak naprawdę trwałymi ideałami platońskimi , ale parametrami działania programu. Nie ma nic naprawdę stała się PORT, SITENAMEczy NUMRUNSi oni nie muszą być zarządzane jako globalnych programów samodzielny. Na przykład, można je upuścić do słownika jako globalnie dostępny pakiet parametrów programu:

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

W Pythonie dostępna jest również funkcja przekazywania parametrów słów kluczowych, która zmniejsza potrzebę użycia APPARENTLY_ANGRY_GLOBAL_VARIABLES:

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

process_data("Bubba's Blog")

W praktyce wiele z tych wartości zostanie (lub powinno być) odczytanych z plików konfiguracyjnych, zmiennych środowiskowych systemu operacyjnego, argumentów wiersza poleceń lub innych źródeł, aby spełnić funkcję odwrócenia zasady / wzorca sterowania . Ale to większa historia na kolejny dzień.

Jonathan Eunice
źródło
1

Tak, jest dość powszechny w większości języków programowania (przynajmniej tych, których używam).

Możesz skorzystać z tego linku Google, aby podzielić się wspólnym stylem między twórcami tego samego zespołu.

Wskazane jest użycie

Type                  |Public          |Internal
Global/Class Constants|CAPS_WITH_UNDER |_CAPS_WITH_UNDER
alain.janinm
źródło