__debug__
Zmienna jest przydatny w części, ponieważ ma wpływ na każdy moduł. Jeśli chcę utworzyć inną zmienną, która działa w ten sam sposób, jak mam to zrobić?
Zmienna (bądźmy oryginalna i nazwijmy ją „foo”) nie musi być prawdziwie globalna, w tym sensie, że jeśli zmienię foo w jednym module, zostanie zaktualizowana w innych. Byłoby dobrze, gdybym mógł ustawić foo przed zaimportowaniem innych modułów, a wtedy zobaczyliby dla niego tę samą wartość.
hasattr(__builtin__, "foo")
.Jeśli potrzebujesz globalnej zmiennej międzymodułowej, może wystarczy prosta globalna zmienna na poziomie modułu.
a.py:
b.py:
c.py:
Test:
Przykład ze świata rzeczywistego: plik global_settings.py Django (chociaż w aplikacjach Django ustawienia są używane przez importowanie obiektu
django.conf.settings
).źródło
a.py
zawieramain()
? Czy to ma znaczenie?if __name__=="__main__"
w nim guard, aby uniknąć uruchamiania nieoczekiwanego kodu podczas importu.id()
aby sprawdzić tożsamość)Uważam, że istnieje wiele okoliczności, w których ma to sens i upraszcza programowanie, aby mieć pewne elementy globalne, które są znane w kilku (ściśle powiązanych) modułach. W tym duchu chciałbym nieco rozwinąć ideę posiadania modułu globali, który jest importowany przez te moduły, które muszą się do nich odnosić.
Gdy jest tylko jeden taki moduł, nazywam go „g”. W nim przypisuję wartości domyślne dla każdej zmiennej, którą zamierzam traktować jako globalną. W każdym module, który używa któregokolwiek z nich, nie używam "from g import var", ponieważ skutkuje to tylko zmienną lokalną, która jest inicjowana z g tylko w czasie importu. Większość odniesień tworzę w postaci g.var i „g”. służy jako stałe przypomnienie, że mam do czynienia ze zmienną, która jest potencjalnie dostępna dla innych modułów.
Jeśli wartość takiej zmiennej globalnej ma być często używana w jakiejś funkcji w module, to ta funkcja może wykonać lokalną kopię: var = g.var. Jednak ważne jest, aby zdać sobie sprawę, że przypisania do var są lokalne, a globalny g.var nie może być aktualizowany bez wyraźnego odniesienia do g.var w przypisaniu.
Zauważ, że możesz również mieć wiele takich modułów globalnych współdzielonych przez różne podzbiory modułów, aby zachować nieco ściślejszą kontrolę. Powodem, dla którego używam krótkich nazw dla moich modułów globalnych, jest uniknięcie zbytniego zaśmiecania kodu ich wystąpieniami. Mając tylko niewielkie doświadczenie, stają się wystarczająco mnemoniczne, mając tylko 1 lub 2 znaki.
Nadal jest możliwe przypisanie do, powiedzmy, gx, gdy x nie zostało już zdefiniowane w g, a inny moduł może wtedy uzyskać dostęp do gx Jednak mimo że interpreter na to zezwala, to podejście nie jest tak przejrzyste i unikam to. Nadal istnieje możliwość przypadkowego utworzenia nowej zmiennej w g w wyniku błędu w nazwie zmiennej dla przypisania. Czasami analiza dir (g) jest przydatna do odkrycia nazw niespodzianek, które mogły powstać w wyniku takiego wypadku.
źródło
Zdefiniuj moduł (nazwij go „globalbaz”) i umieść w nim zdefiniowane zmienne. Wszystkie moduły korzystające z tego „pseudoglobalnego” powinny importować moduł „globalbaz” i odnosić się do niego przy użyciu „globalbaz.var_name”
Działa to niezależnie od miejsca zmiany, możesz zmienić zmienną przed lub po imporcie. Zaimportowany moduł użyje najnowszej wartości. (Przetestowałem to na przykładzie zabawki)
Dla wyjaśnienia, globalbaz.py wygląda tak:
źródło
Możesz przekazać globale jednego modułu innemu:
W module A:
W module B:
źródło
Zmienne globalne to zwykle zły pomysł, ale możesz to zrobić, przypisując do
__builtins__
:Ponadto same moduły są zmiennymi, do których można uzyskać dostęp z dowolnego modułu. Jeśli więc zdefiniujesz moduł o nazwie
my_globals.py
:Następnie możesz użyć tego również z dowolnego miejsca:
Używanie modułów zamiast modyfikowania
__builtins__
jest generalnie czystszym sposobem robienia tego typu obiektów globalnych.źródło
__builtins__
jest osobliwością CPythona, naprawdę nie powinieneś go używać - lepiej używać__builtin__
(lubbuiltins
w Pythonie3), jak pokazuje akceptowana odpowiedźMożesz to już zrobić za pomocą zmiennych na poziomie modułu. Moduły są takie same bez względu na to, z jakiego modułu są importowane. Możesz więc uczynić zmienną zmienną na poziomie modułu w dowolnym module, w którym ma sens, i uzyskać do niej dostęp lub przypisać do niej z innych modułów. Byłoby lepiej wywołać funkcję, aby ustawić wartość zmiennej lub uczynić ją właściwością jakiegoś pojedynczego obiektu. W ten sposób, jeśli w końcu będziesz musiał uruchomić jakiś kod po zmianie zmiennej, możesz to zrobić bez uszkadzania zewnętrznego interfejsu modułu.
Zwykle nie jest to świetny sposób robienia rzeczy - rzadko używa się globali - ale myślę, że jest to najczystszy sposób na zrobienie tego.
źródło
Chciałem zamieścić odpowiedź, że jest przypadek, w którym zmienna nie zostanie znaleziona.
Import cykliczny może zakłócić zachowanie modułu.
Na przykład:
first.py
second.py
main.py
W tym przykładzie powinno to być oczywiste, ale w przypadku dużej bazy kodu może to być naprawdę zagmatwane.
źródło
To brzmi jak modyfikacja
__builtin__
przestrzeni nazw. Aby to zrobić:Nie używaj
__builtins__
bezpośrednio (zwróć uwagę na dodatkowe „s”) - najwyraźniej może to być słownik lub moduł. Dzięki ΤΖΩΤΖΙΟΥ za wskazanie tego, więcej można znaleźć tutaj .Teraz
foo
jest dostępny do użytku wszędzie.Generalnie nie polecam tego robić, ale użycie tego zależy od programisty.
Przypisanie do niego musi być wykonane jak powyżej, samo ustawienie
foo = 'some-other-value'
spowoduje ustawienie go tylko w bieżącej przestrzeni nazw.źródło
Używam tego do kilku wbudowanych prymitywnych funkcji, których naprawdę brakowało. Jednym z przykładów jest funkcja wyszukiwania, która ma taką samą semantykę użycia jak filtr, mapowanie, redukcja.
Po uruchomieniu tego (na przykład przez zaimportowanie w pobliżu punktu wejścia) wszystkie moduły mogą używać funkcji find (), tak jakby, oczywiście, została wbudowana.
Uwaga: możesz to oczywiście zrobić za pomocą filtra i innej linii, aby przetestować zerową długość lub z redukcją w jednym rodzaju dziwnej linii, ale zawsze uważałem, że to dziwne.
źródło
Mogłem uzyskać zmienne modyfikowalne (lub mutowalne ) między modułami za pomocą słownika:
Podczas uruchamiania
test_wait_app_up_fail
rzeczywisty limit czasu wynosi 3 sekundy.źródło
Zastanawiałem się, czy byłoby możliwe uniknięcie niektórych wad używania zmiennych globalnych (patrz np. Http://wiki.c2.com/?GlobalVariablesAreBad ) poprzez użycie przestrzeni nazw klas zamiast globalnej / modułowej przestrzeni nazw do przekazywania wartości zmiennych . Poniższy kod wskazuje, że te dwie metody są zasadniczo identyczne. Korzystanie z przestrzeni nazw klas ma pewną przewagę, jak wyjaśniono poniżej.
Poniższe fragmenty kodu pokazują również, że atrybuty lub zmienne mogą być dynamicznie tworzone i usuwane zarówno w globalnych / modułowych przestrzeniach nazw, jak iw przestrzeniach nazw klas.
wall.py
Nazywam ten moduł „ścianą”, ponieważ jest używany do odbijania zmiennych od. Będzie działać jako przestrzeń do tymczasowego definiowania zmiennych globalnych i atrybutów całej klasy pustej klasy „router”.
source.py
Ten moduł importuje ścianę i definiuje pojedynczą funkcję,
sourcefn
która definiuje wiadomość i emituje ją przez dwa różne mechanizmy, jeden poprzez globale, a drugi przez funkcję routera. Zwróć uwagę, że zmiennewall.msg
iwall.router.message
są zdefiniowane tutaj po raz pierwszy w odpowiednich przestrzeniach nazw.dest.py
Ten moduł definiuje funkcję,
destfn
która wykorzystuje dwa różne mechanizmy do odbierania wiadomości emitowanych przez źródło. Uwzględnia możliwość, że zmienna „msg” może nie istnieć.destfn
usuwa także zmienne po ich wyświetleniu.main.py
Ten moduł wywołuje po kolei wcześniej zdefiniowane funkcje. Po pierwszym wywołaniu
dest.destfn
zmiennychwall.msg
iwall.router.msg
już nie istnieją.Dane wyjściowe z programu to:
global: Witaj, świecie!
router: Witaj, świecie!
global: brak wiadomości
router: brak wiadomości
Powyższe fragmenty kodu pokazują, że mechanizm moduł / globalny i mechanizm zmiennej klasy / klasy są zasadniczo identyczne.
Jeśli ma być współdzielonych wiele zmiennych, zanieczyszczeniem przestrzeni nazw można zarządzać za pomocą kilku modułów ściennych, np. Wall1, wall2 itp. Lub definiując kilka klas typu routera w jednym pliku. Ta ostatnia jest nieco uporządkowana, więc być może stanowi marginalną zaletę w stosowaniu mechanizmu zmiennych klas.
źródło