Jak mogę utworzyć lub użyć zmiennej globalnej w funkcji?
Jeśli utworzę zmienną globalną w jednej funkcji, jak mogę użyć tej zmiennej globalnej w innej funkcji? Czy muszę przechowywać zmienną globalną w zmiennej lokalnej funkcji, która potrzebuje jej dostępu?
python
global-variables
scope
użytkownik46646
źródło
źródło
global
słowa kluczowego, jest to, że globały są niebezpieczne. Raczej dlatego, że język nie wymaga jawnego deklarowania zmiennych i automatycznie zakłada, że przypisywana zmienna ma zakres funkcji, chyba że powiesz jej inaczej. Słowoglobal
kluczowe jest środkiem zapewniającym, że jest inaczej.f2()
zmienił stan, więc terazf3()
może zrobić coś nieoczekiwanego? Funkcje mogą teraz działać niezależnie od stanu programu zewnętrznego.Jeśli dobrze rozumiem twoją sytuację, to, co widzisz, jest wynikiem tego, jak Python obsługuje lokalne (funkcyjne) i globalne (modułowe) przestrzenie nazw.
Powiedz, że masz taki moduł:
Możesz spodziewać się, że to wydrukuje 42, ale zamiast tego wydrukuje 5. Jak już wspomniano, jeśli dodasz
global
deklarację „ ”func1()
,func2()
wydrukuje 42.To, co się tutaj dzieje, polega na tym, że Python zakłada, że każda nazwa przypisana w dowolnym miejscu funkcji jest lokalna dla tej funkcji, chyba że wyraźnie zaznaczono inaczej. Jeśli czyta tylko z nazwy, a nazwa nie istnieje lokalnie, spróbuje wyszukać nazwę w dowolnym zawierającym zakresie (np. Globalnym zasięgu modułu).
myGlobal
Dlatego po przypisaniu 42 do nazwy Python tworzy zmienną lokalną, która przesłania zmienną globalną o tej samej nazwie. Ten lokalny wykracza poza zakres i jest zwracany w śmieciach pofunc1()
powrocie; tymczasemfunc2()
nigdy nie widzi niczego poza (niezmodyfikowaną) nazwą globalną. Zauważ, że decyzja o przestrzeni nazw ma miejsce w czasie kompilacji, a nie w czasie wykonywania - jeśli miałbyś odczytać wartośćmyGlobal
insidefunc1()
przed przypisaniem do niej, dostałbyśUnboundLocalError
, ponieważ Python już zdecydował, że musi to być zmienna lokalna, ale nie ma jeszcze żadnej wartości z tym związanej. Ale używając instrukcji „global
”, mówisz Pythonowi, że powinien szukać innej nazwy zamiast przypisywać ją lokalnie.(Uważam, że takie zachowanie powstało głównie dzięki optymalizacji lokalnych przestrzeni nazw - bez tego zachowania maszyna wirtualna Pythona musiałaby wykonywać co najmniej trzy wyszukiwania nazw za każdym razem, gdy nowa funkcja jest przypisywana do funkcji (aby upewnić się, że nazwa nie już istnieją na poziomie modułu / wbudowanego), co znacznie spowolniłoby bardzo częstą operację.)
źródło
MyGlobal = 5
x
jest lokalna, różni się od sprawdzania w czasie wykonywania, czy nazwa lokalna była związana z wartością przed jej pierwszym użyciem.MY_GLOBAL = 5
. Zobacz Przewodnik po stylu dla kodu Python .Możesz zapoznać się z pojęciem przestrzeni nazw . W Pythonie moduł jest naturalnym miejscem dla danych globalnych :
Konkretne zastosowanie globalnego modułu jest opisane tutaj - Jak współdzielić zmienne globalne między modułami? , a dla kompletności treść jest udostępniana tutaj:
źródło
config.x
mi się to, czy mogę się go pozbyć? Przyszedłem z,x = lambda: config.x
a potem mam nową wartość wx()
. z jakiegoś powodu posiadanie mniea = config.x
nie rozwiązuje problemu.from config import x
rozwiązuje to?Python używa prostej heurystyki, aby zdecydować, z którego zakresu powinna załadować zmienną, między lokalną a globalną. Jeśli nazwa zmiennej pojawia się po lewej stronie przypisania, ale nie jest deklarowana jako globalna, zakłada się, że jest lokalna. Jeśli nie pojawia się po lewej stronie zadania, przyjmuje się, że ma charakter globalny.
Zobacz, jak baz, który pojawia się po lewej stronie przypisania w
foo()
, jest jedynąLOAD_FAST
zmienną.źródło
for
pętli i nazwisko poas
wwith
iexcept
wypowiedzi również są zobowiązane do.as
wexcept
klauzuli nie było to dla mnie oczywiste. Ale jest automatycznie usuwany, aby zaoszczędzić pamięć.as ...
celu w procedurze obsługi wyjątków.Jeśli chcesz odwoływać się do zmiennej globalnej w funkcji, możesz użyć słowa kluczowego global, aby zadeklarować, które zmienne są globalne. Nie musisz go używać we wszystkich przypadkach (jak ktoś tutaj błędnie twierdzi) - jeśli nazwy, do której odwołuje się wyrażenie, nie można znaleźć w zasięgu lokalnym lub zakresach w funkcjach, w których ta funkcja jest zdefiniowana, jest sprawdzana wśród globalnych zmienne.
Jeśli jednak przypiszesz do nowej zmiennej, która nie jest zadeklarowana jako globalna w funkcji, zostanie ona domyślnie zadeklarowana jako lokalna i może przyćmić dowolną istniejącą zmienną globalną o tej samej nazwie.
Przydatne są także zmienne globalne, w przeciwieństwie do fanatyków OOP, którzy twierdzą inaczej - szczególnie w przypadku mniejszych skryptów, w których OOP jest przesadą.
źródło
Możemy stworzyć globalny za pomocą następującej funkcji:
Napisanie funkcji tak naprawdę nie uruchamia jej kodu. Dlatego nazywamy
create_global_variable
funkcję:Używanie globałów bez modyfikacji
Możesz po prostu z niego korzystać, o ile nie spodziewasz się zmienić obiektu, na który wskazuje:
Na przykład,
a teraz możemy użyć zmiennej globalnej:
Modyfikacja zmiennej globalnej z wnętrza funkcji
Aby wskazać zmienną globalną na inny obiekt, musisz ponownie użyć słowa kluczowego global:
Zauważ, że po napisaniu tej funkcji kod, który ją zmienia, wciąż nie działa:
Po wywołaniu funkcji:
widzimy, że zmienna globalna została zmieniona.
global_variable
Nazwa wskazuje teraz'Bar'
:Zauważ, że „globalny” w Pythonie nie jest tak naprawdę globalny - jest tylko globalny do poziomu modułu. Jest więc dostępny tylko dla funkcji zapisanych w modułach, w których jest globalny. Funkcje zapamiętują moduł, w którym zostały napisane, więc kiedy są eksportowane do innych modułów, nadal szukają modułu, w którym zostały utworzone, aby znaleźć zmienne globalne.
Zmienne lokalne o tej samej nazwie
Jeśli utworzysz zmienną lokalną o tej samej nazwie, przyćmi ona zmienną globalną:
Ale użycie tej źle nazwanej zmiennej lokalnej nie zmienia zmiennej globalnej:
Pamiętaj, że powinieneś unikać używania lokalnych zmiennych o takich samych nazwach jak globale, chyba że wiesz dokładnie, co robisz i masz bardzo dobry powód, aby to zrobić. Nie spotkałem jeszcze takiego powodu.
Takie samo zachowanie uzyskujemy na zajęciach
W komentarzu pojawia się pytanie:
Tutaj pokazuję, że uzyskujemy takie samo zachowanie w metodach, jak w przypadku zwykłych funkcji:
I teraz:
Proponuję jednak zamiast używać zmiennych globalnych używać atrybutów klas, aby uniknąć zaśmiecania przestrzeni nazw modułów. Zauważ też, że nie używamy
self
tutaj argumentów - mogą to być metody klasowe (przydatne, gdy mutujemy atrybut klasy ze zwykłegocls
argumentu) lub metody statyczne (nieself
lubcls
).źródło
Oprócz już istniejących odpowiedzi i aby było to bardziej mylące:
Źródło: Jakie są reguły dla zmiennych lokalnych i globalnych w Pythonie? .
źródło
Przy równoległym wykonywaniu zmienne globalne mogą powodować nieoczekiwane wyniki, jeśli nie rozumiesz, co się dzieje. Oto przykład użycia zmiennej globalnej w ramach wieloprocesowego przetwarzania. Widzimy wyraźnie, że każdy proces działa z własną kopią zmiennej:
Wynik:
źródło
Mówisz o użyciu następującej metody:
Ale lepszym sposobem jest użycie globalnej zmiennej w ten sposób:
Oba dają taką samą moc wyjściową.
źródło
Jak się okazuje, odpowiedź jest zawsze prosta.
Oto mały przykładowy moduł z prostym sposobem pokazania go w
main
definicji:Oto jak to pokazać w
main
definicji:Ten prosty kod działa w ten sposób i zostanie wykonany. Mam nadzieję, że to pomoże.
źródło
global_vars
i inicjuję daneinit_global_vars
, które są wywoływane w skrypcie startowym. Następnie po prostu tworzę metodę akcesora dla każdej zdefiniowanej zmiennej globalnej. Mam nadzieję, że będę mógł to głosować wiele razy! Dzięki Peter!Musisz odwoływać się do zmiennej globalnej w każdej funkcji, której chcesz użyć.
Następująco:
źródło
W rzeczywistości nie przechowujesz globalnego w zmiennej lokalnej, po prostu tworzysz lokalne odwołanie do tego samego obiektu, do którego odnosi się twoje oryginalne odwołanie globalne. Pamiętaj, że prawie wszystko w Pythonie jest nazwą odnoszącą się do obiektu i nic nie jest kopiowane podczas zwykłej operacji.
Jeśli nie musisz jawnie określać, kiedy identyfikator ma odnosić się do predefiniowanej globalnej, prawdopodobnie musiałbyś jawnie określić, kiedy identyfikator jest nową zmienną lokalną (na przykład za pomocą czegoś takiego jak polecenie „var” widoczne w JavaScript). Ponieważ zmienne lokalne są bardziej powszechne niż zmienne globalne w dowolnym poważnym i nietrywialnym systemie, w większości przypadków system Pythona ma większy sens.
Państwo mogłoby mieć język, który próbował odgadnąć, wykorzystując zmienną globalną gdyby istniał lub utworzenie zmiennej lokalnej, czy nie. Byłoby to jednak bardzo podatne na błędy. Na przykład zaimportowanie innego modułu może przypadkowo wprowadzić zmienną globalną o tej nazwie, zmieniając zachowanie twojego programu.
źródło
Spróbuj tego:
źródło
Jeśli masz zmienną lokalną o tej samej nazwie, możesz chcieć użyć
globals()
funkcji .źródło
Następnie i jako dodatek użyj pliku, który zawiera wszystkie zmienne globalne wszystkie zadeklarowane lokalnie, a następnie
import as
:Plik initval.py :
Plik getstocks.py :
źródło
import ... as ...
? Dlaczego nie tylkoimport ...
?global
:-) => +1 :-) Edytuj swoją odpowiedź, aby wyjaśnić te zapytania, które mogą mieć także inni ludzie. PozdrawiamZapis do jawnych elementów tablicy globalnej najwyraźniej nie wymaga globalnej deklaracji, chociaż zapis do niej „hurtowy” ma ten wymóg:
źródło
Dodam to, ponieważ nie widziałem tego w żadnej innej odpowiedzi i może być przydatne dla kogoś, kto zmaga się z czymś podobnym.
globals()
Funkcja zwraca zmienny słownika globalny symbol, gdzie można „magicznie” dostępne do reszty kodu dane wprowadzić. Na przykład:i
Pozwoli tylko zrzucić / załadować zmienne zi do globalnej przestrzeni nazw. Super wygodne, bez musków, bez zamieszania. Jestem pewien, że to tylko Python 3.
źródło
globals()
zawsze zwraca globały dostępne w kontekście lokalnym, więc mutacja tutaj może nie zostać odzwierciedlona w innym module.Odwołaj się do przestrzeni nazw klas, w której chcesz pokazać zmianę.
W tym przykładzie runner używa max z konfiguracji pliku. Chcę, aby mój test zmienił wartość maks gdy biegacz go używa.
main / config.py
main / runner.py
testy / runner_test.py
źródło
Globale są w porządku - z wyjątkiem wieloprocesowego
Globalne w związku z wieloprocesowym przetwarzaniem na różnych platformach / środowiskach, takich jak Windows / Mac OS z jednej strony i Linux z drugiej, są kłopotliwe.
Pokażę to na prostym przykładzie, wskazując problem, na który wpadłem jakiś czas temu.
Jeśli chcesz zrozumieć, dlaczego sprawy różnią się w systemach Windows / MacO i Linux, musisz to wiedzieć, domyślny mechanizm uruchamiania nowego procesu w ...
Różnią się one inicjalizacją przydziału pamięci ... (ale nie wchodzę w to tutaj).
Rzućmy okiem na problem / przykład ...
Windows
Jeśli uruchomisz to w systemie Windows (i przypuszczam, że także w systemie MacOS), otrzymasz następujące dane wyjściowe ...
Linux
Jeśli uruchomisz to w systemie Linux, zamiast tego otrzymasz następujące.
źródło