Odpowiedzi:
To nie ma nic wspólnego z Pythonem; zmienne globalne są złe w każdym języku programowania.
Jednak stałe globalne nie są koncepcyjnie tym samym, co zmienne globalne ; globalne stałe są całkowicie nieszkodliwe. W Pythonie rozróżnienie między nimi jest wyłącznie konwencją: CONSTANTS_ARE_CAPITALIZED
i globals_are_not
.
Powodem, dla którego zmienne globalne są złe, jest to, że umożliwiają one funkcjom wywoływanie ukrytych (nieoczywistych, zaskakujących, trudnych do wykrycia, trudnych do zdiagnozowania) skutków ubocznych, co prowadzi do zwiększenia złożoności, potencjalnie prowadząc do kodu Spaghetti .
Jednak rozsądne użycie stanu globalnego jest dopuszczalne (podobnie jak stan lokalny i zmienność) nawet w programowaniu funkcjonalnym, zarówno w celu optymalizacji algorytmu, zmniejszonej złożoności, buforowania i zapamiętywania, jak i praktyczności portowania struktur pochodzących głównie z imperatywnej bazy kodu.
Podsumowując, na twoje pytanie można odpowiedzieć na wiele sposobów, więc najlepiej jest po prostu wygooglować „dlaczego zmienne globalne są złe”. Kilka przykładów:
Jeśli chcesz wejść głębiej i dowiedzieć się, dlaczego chodzi o efekty uboczne i wiele innych pouczających rzeczy, powinieneś nauczyć się programowania funkcjonalnego:
Tak, w teorii globale (i ogólnie „państwo”) są złe. W praktyce, jeśli zajrzysz do katalogu pakietów swojego Pythona, zauważysz, że większość modułów zaczyna się od zestawu globalnych deklaracji. Oczywiście ludzie nie mają z nimi problemu.
W szczególności w Pythonie, widoczność elementów globalnych jest ograniczona do modułu, dlatego nie ma „prawdziwych” elementów globalnych, które wpływają na cały program - co czyni je o wiele mniej szkodliwymi. Kolejna kwestia: nie ma const
, więc jeśli potrzebujesz stałej, musisz użyć globalnej.
W mojej praktyce, jeśli zdarzy mi się zmodyfikować global w funkcji, zawsze deklaruję to z global
, nawet jeśli technicznie nie ma takiej potrzeby, jak w:
cache = {}
def foo(args):
global cache
cache[args] = ...
To sprawia, że manipulacje globali są łatwiejsze do wyśledzenia.
Osobista opinia na ten temat jest taka, że używanie zmiennych globalnych w logice funkcji oznacza, że jakiś inny kod może zmienić logikę i oczekiwane wyniki tej funkcji, co bardzo utrudni debugowanie (szczególnie w dużych projektach) i utrudni testowanie także.
Ponadto, jeśli weźmiesz pod uwagę inne osoby czytające Twój kod (społeczność open source, koledzy itp.), Będą mieli trudności ze zrozumieniem, gdzie ustawiana jest zmienna globalna, gdzie została zmieniona i czego można się spodziewać po tej zmiennej globalnej. do funkcji izolowanej, że jej funkcjonalność można określić, odczytując samą definicję funkcji.
Uważam, że czysty i (prawie) wolny od błędów kod powinien mieć funkcje możliwie najczystsze (zobacz czyste funkcje ). Czysta funkcja to taka, która ma następujące warunki:
Posiadanie zmiennych globalnych narusza co najmniej jedno z powyższych, jeśli nie oba, ponieważ kod zewnętrzny może prawdopodobnie spowodować nieoczekiwane rezultaty.
Inna jasna definicja czystych funkcji: „Czysta funkcja to funkcja, która przyjmuje wszystkie swoje dane wejściowe jako jawne argumenty i produkuje wszystkie swoje wyniki jako jawne wyniki ”. [1] . Posiadanie zmiennych globalnych narusza ideę czystych funkcji, ponieważ dane wejściowe i być może jedno z wyjść (zmienna globalna) nie są jawnie podawane ani zwracane.
Dalej, że jeśli wziąć pod uwagę jednostki testowanie i zasady pierwszej ( F testy AST I testy ndependent, R epeatable, S elf-zatwierdzania i T imely) prawdopodobnie będzie naruszać niezależnych testach zasada (co oznacza, że testy nie są uzależnione na siebie).
Posiadanie zmiennej globalnej (nie zawsze), ale w większości przypadków (przynajmniej z tego, co widziałem do tej pory) polega na przygotowaniu i przekazaniu wyników do innych funkcji. To również narusza tę zasadę. Jeśli zmienna globalna została użyta w ten sposób (tj. Zmienna globalna użyta w funkcji X musi być najpierw ustawiona w funkcji Y), oznacza to, że aby przetestować funkcję X należy najpierw uruchomić test / uruchomić funkcję Y.
Z drugiej strony, jak wspominali już inni, użycie zmiennej globalnej jako zmiennej „stałej” może być nieco lepsze, ponieważ język nie obsługuje stałych. Jednak zawsze wolę pracować z klasami i mieć „stałe” jako składową klasy i nie używać w ogóle zmiennej globalnej. Jeśli masz kod, którego dwie różne klasy wymagają do współużytkowania zmiennej globalnej, prawdopodobnie będziesz musiał zrefaktoryzować swoje rozwiązanie i uniezależnić swoje klasy.
Uważam, że nie powinno się używać globali. Ale jeśli zostaną użyte, autorzy powinni rozważyć pewne zasady (być może wspomniane powyżej oraz inne zasady i dobre praktyki inżynierii oprogramowania), aby kod był bardziej przejrzysty i prawie wolny od błędów.
Są niezbędne, a ekran jest dobrym przykładem. Jednak w środowisku wielowątkowym lub w którym uczestniczy wielu programistów, w praktyce często pojawia się pytanie: kto (błędnie) to ustawił lub wyczyścił? W zależności od architektury analiza może być kosztowna i często wymagana. Podczas odczytu zmiennej globalnej może być w porządku, zapis do niej musi być kontrolowany, na przykład przez pojedynczy wątek lub klasę chroniącą wątki. Stąd globalne wojny rodzą obawę przed wysokimi kosztami rozwoju możliwymi przez konsekwencje, dla których same są uważane za złe. Dlatego ogólnie dobrą praktyką jest utrzymywanie niskiej liczby zmiennych globalnych.
eval
,import *
, konkatenacji ciągów , zmiennejid
, cienie atrybutów )