Używanie zmiennych globalnych w funkcji

Jak 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?

Author: Aran-Fey, 2009-01-08

18 answers

Możesz użyć zmiennej globalnej w innych funkcjach deklarując ją jako global w każdej funkcji, która jej przypisuje:

globvar = 0

def set_globvar_to_one():
    global globvar    # Needed to modify global copy of globvar
    globvar = 1

def print_globvar():
    print(globvar)     # No need for global declaration to read value of globvar

set_globvar_to_one()
print_globvar()       # Prints 1

Wyobrażam sobie, że powodem tego jest to, że ponieważ zmienne globalne są tak niebezpieczne, Python chce upewnić się, że naprawdę wiesz, z czym się bawisz, wyraźnie wymagając słowa kluczowego global.

Zobacz inne odpowiedzi, jeśli chcesz udostępnić zmienną globalną między modułami.

 3587
Author: Paul Stephenson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-01 03:40:54

Jeśli dobrze rozumiem twoją sytuację, to co widzisz jest wynikiem tego, jak Python obsługuje lokalne (function) i globalne (module) przestrzenie nazw.

Powiedzmy, że masz taki moduł:

# sample.py
myGlobal = 5

def func1():
    myGlobal = 42

def func2():
    print myGlobal

func1()
func2()

Możesz oczekiwać, że wydrukuje 42, ale zamiast tego wydrukuje 5. Jak już wspomniano, jeśli dodasz deklarację "global " do func1(), to func2() wydrukuje 42.

def func1():
    global myGlobal
    myGlobal = 42

Chodzi o to, że Python zakłada, że każda nazwa, która jest przypisana to , gdziekolwiek wewnątrz funkcji, jest lokalne dla tej funkcji, chyba że wyraźnie powiedziano inaczej. Jeśli tylko odczytuje z nazwy, a nazwa nie istnieje lokalnie, spróbuje wyszukać nazwę w dowolnych zakresach (np. globalny zakres modułu).

Kiedy przypisujesz 42 do nazwy myGlobal, Python tworzy zmienną lokalną, która zasłania zmienną globalną o tej samej nazwie. Ten lokalny wychodzi poza zasięg i jest zbierany kiedy func1() zwraca; tymczasem func2() nigdy nie widzi niczego innego niż (niezmodyfikowana) nazwa globalna. Zauważ, że decyzja w tej przestrzeni nazw ma miejsce w czasie kompilacji, a nie w czasie wykonywania-gdybyś odczytał wartość myGlobal wewnątrz func1() przed przypisaniem do niej, otrzymałbyś UnboundLocalError, ponieważ Python już zdecydował, że musi to być zmienna lokalna, ale nie ma jeszcze żadnej wartości z nią związanej. Ale używając instrukcji ' global', mówisz Pythonowi, że powinien szukać gdzie indziej nazwy zamiast przypisywanie do niego lokalnie.

(uważam, że to 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 nazwa jest przypisywana do funkcji (aby upewnić się, że nazwa nie istnieje już na poziomie modułu/wbudowanego), co znacznie spowolniłoby bardzo powszechną operację.)

 678
Author: Jeff Shannon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-16 18:01:50

Możesz zapoznać się z pojęciem przestrzeni nazw . W Pythonie moduł jest naturalnym miejscem dla globalnych Danych:

Każdy moduł ma własną prywatną tabelę symboli, która jest używana jako globalna tabela symboli przez wszystkie funkcje zdefiniowane w module. W ten sposób autor modułu może używać zmiennych globalnych w module bez obawy o przypadkowe zderzenia ze zmiennymi globalnymi użytkownika. Z drugiej strony, jeśli wiesz, co robisz, możesz dotknij zmiennych globalnych modułu z tą samą notacją używaną do odwoływania się do jego funkcji, modname.itemname.

Specyficzne użycie global-in-a-module jest opisane tutaj- Jak-robić-i-udostępniać-globalne-zmienne-w-modułach , a dla kompletności zawartość jest udostępniana tutaj:

Kanonicznym sposobem dzielenia się informacjami pomiędzy modułami w ramach jednego programu jest utworzenie specjalnego modułu konfiguracyjnego (często nazywanego config lub cfg). Wystarczy zaimportować moduł konfiguracji we wszystkich moduły aplikacji; Moduł staje się wtedy dostępny jako nazwa globalna. Ponieważ istnieje tylko jedna instancja każdego modułu, wszelkie zmiany wprowadzone w obiekcie modułu są odzwierciedlane wszędzie. Na przykład:

Plik: config.py

x = 0   # Default value of the 'x' configuration setting

Plik: mod.py

import config
config.x = 1

Plik: main.py

import config
import mod
print config.x
 180
Author: gimel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-24 12:07:01

Python używa prostej heurystyki, aby zdecydować, z którego zakresu powinna załadować zmienną, pomiędzy lokalną a globalną. Jeśli nazwa zmiennej pojawia się po lewej stronie przypisania, ale nie jest zadeklarowana jako globalna, przyjmuje się, że jest lokalna. Jeśli nie pojawia się po lewej stronie przypisania, przyjmuje się, że ma charakter globalny.

>>> import dis
>>> def foo():
...     global bar
...     baz = 5
...     print bar
...     print baz
...     print quux
... 
>>> dis.disassemble(foo.func_code)
  3           0 LOAD_CONST               1 (5)
              3 STORE_FAST               0 (baz)

  4           6 LOAD_GLOBAL              0 (bar)
              9 PRINT_ITEM          
             10 PRINT_NEWLINE       

  5          11 LOAD_FAST                0 (baz)
             14 PRINT_ITEM          
             15 PRINT_NEWLINE       

  6          16 LOAD_GLOBAL              1 (quux)
             19 PRINT_ITEM          
             20 PRINT_NEWLINE       
             21 LOAD_CONST               0 (None)
             24 RETURN_VALUE        
>>> 

Zobacz jak baz, który pojawia się po lewej stronie przypisania w foo(), jest jedyną zmienną LOAD_FAST.

 76
Author: SingleNegationElimination,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-12 12:35:08

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 jej używać we wszystkich przypadkach ( jak ktoś tutaj błędnie twierdzi) - jeśli nazwa, do której odwołuje się wyrażenie, nie może zostać znaleziona w lokalnym zakresie lub zakresach w funkcjach, w których ta funkcja jest zdefiniowana, jest ona sprawdzana wśród zmiennych globalnych.

Jeśli jednak przypiszesz do nowej zmiennej nie zadeklarowanej jako globalna w funkcji, to domyślnie zadeklarowana jako lokalna i może przyćmić dowolną istniejącą globalną zmienną o tej samej nazwie.

Również zmienne globalne są przydatne, w przeciwieństwie do niektórych fanatyków OOP, którzy twierdzą inaczej-szczególnie dla mniejszych skryptów, gdzie OOP jest przesadą.

 50
Author: J S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-04 22:00:48

Oprócz już istniejących odpowiedzi i aby było to bardziej mylące:

W Pythonie zmienne odwołujące się tylko do funkcji są implicite global . Jeśli zmiennej zostanie przypisana nowa wartość w dowolnym miejscu w ciele funkcji przyjmuje się, że jest to lokalna . Jeśli zmienna jest kiedykolwiek przypisana nowa wartość wewnątrz funkcji, zmienna jest w domyśle lokalny i musisz jawnie zadeklarować go jako "globalny".

Choć trochę zaskakujące na początku, chwila zastanowienia wyjaśnia to. Z jednej strony, Wymaganie globalnego dla przypisanych zmiennych zapewnia bar przed niezamierzonymi skutkami ubocznymi. Z drugiej strony, gdyby global był wymagane dla wszystkich globalnych referencji, będziesz używać global all the czas. Musisz zadeklarować jako globalne każde odniesienie do wbudowanego funkcji lub do komponentu importowanego modułu. Ten bałagan by pokonanie przydatności globalnej deklaracji do identyfikacji skutki uboczne.

Źródło: jakie są reguły dla zmiennych lokalnych i globalnych w Pythonie?.

 38
Author: Rauni Lillemets,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-20 10:36:29

Jeśli stworzę zmienną globalną w jednej funkcji, jak mogę użyć tej zmiennej w innej funkcji?

Możemy utworzyć globalny o następującej funkcji:

def create_global_variable():
    global global_variable # must declare it to be a global first
    # modifications are thus reflected on the module's global scope
    global_variable = 'Foo' 

Pisanie funkcji nie uruchamia jej kodu. Nazywamy więc create_global_variable funkcją:

>>> create_global_variable()

Używanie globali bez modyfikacji

Możesz go po prostu użyć, tak długo, jak nie spodziewasz się zmienić, na który obiekt wskazuje:

Na przykład,

def use_global_variable():
    return global_variable + '!!!'

A teraz możemy użyć zmiennej globalnej:

>>> use_global_variable()
'Foo!!!'

Modyfikacja zmiennej globalnej z wnętrza funkcji

Aby wskazać zmienną globalną na inny obiekt, musisz ponownie użyć słowa kluczowego global:

def change_global_variable():
    global global_variable
    global_variable = 'Bar'

Zauważ, że po napisaniu tej funkcji kod faktycznie zmieniający ją nadal nie działa:

>>> use_global_variable()
'Foo!!!'

Więc po wywołaniu funkcji:

>>> change_global_variable()

Widzimy, że zmienna globalna została zmieniona. global_variable nazwa wskazuje teraz na 'Bar':

>>> use_global_variable()
'Bar!!!'

Zauważ, że" globalny " w Pythonie nie jest naprawdę globalny - jest tylko globalny do poziomu modułu. Jest więc dostępna tylko dla funkcji napisanych w modułach, w których jest globalna. Funkcje zapamiętują moduł, w którym są napisane, więc gdy są eksportowane do innych modułów, nadal szukają w module, 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 zmienną globalną:

def use_local_with_same_name_as_global():
    # bad name for a local variable, though.
    global_variable = 'Baz' 
    return global_variable + '!!!'

>>> use_local_with_same_name_as_global()
'Baz!!!'

Ale użycie tej błędnie nazwanej zmiennej lokalnej nie zmienia zmiennej globalnej:

>>> use_global_variable()
'Bar!!!'

Zauważ, że powinieneś unikać używania zmiennych lokalnych o takich samych nazwach jak globals, chyba że wiesz dokładnie, co robisz i masz bardzo dobry powód, aby to zrobić. Nie spotkałem się jeszcze z takim powodem.

 32
Author: Aaron Hall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-20 16:32:18

Przy wykonywaniu równoległym zmienne globalne mogą powodować nieoczekiwane wyniki, jeśli nie rozumiesz, co się dzieje. Oto przykład użycia zmiennej globalnej w ramach przetwarzania wieloprocesorowego. Możemy wyraźnie zobaczyć, że każdy proces pracuje z własną kopią zmiennej:

import multiprocessing
import os
import random
import sys
import time

def worker(new_value):
    old_value = get_value()
    set_value(random.randint(1, 99))
    print('pid=[{pid}] '
          'old_value=[{old_value:2}] '
          'new_value=[{new_value:2}] '
          'get_value=[{get_value:2}]'.format(
          pid=str(os.getpid()),
          old_value=old_value,
          new_value=new_value,
          get_value=get_value()))

def get_value():
    global global_variable
    return global_variable

def set_value(new_value):
    global global_variable
    global_variable = new_value

global_variable = -1

print('before set_value(), get_value() = [%s]' % get_value())
set_value(new_value=-2)
print('after  set_value(), get_value() = [%s]' % get_value())

processPool = multiprocessing.Pool(processes=5)
processPool.map(func=worker, iterable=range(15))

Wyjście:

before set_value(), get_value() = [-1]
after  set_value(), get_value() = [-2]
pid=[53970] old_value=[-2] new_value=[ 0] get_value=[23]
pid=[53971] old_value=[-2] new_value=[ 1] get_value=[42]
pid=[53970] old_value=[23] new_value=[ 4] get_value=[50]
pid=[53970] old_value=[50] new_value=[ 6] get_value=[14]
pid=[53971] old_value=[42] new_value=[ 5] get_value=[31]
pid=[53972] old_value=[-2] new_value=[ 2] get_value=[44]
pid=[53973] old_value=[-2] new_value=[ 3] get_value=[94]
pid=[53970] old_value=[14] new_value=[ 7] get_value=[21]
pid=[53971] old_value=[31] new_value=[ 8] get_value=[34]
pid=[53972] old_value=[44] new_value=[ 9] get_value=[59]
pid=[53973] old_value=[94] new_value=[10] get_value=[87]
pid=[53970] old_value=[21] new_value=[11] get_value=[21]
pid=[53971] old_value=[34] new_value=[12] get_value=[82]
pid=[53972] old_value=[59] new_value=[13] get_value=[ 4]
pid=[53973] old_value=[87] new_value=[14] get_value=[70]
 29
Author: Bohdan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-03 02:34:20

Musisz odwołać się do zmiennej globalnej w każdej funkcji, której chcesz użyć.

Następująco:

var = "test"

def printGlobalText():
    global var #wWe are telling to explicitly use the global version
    var = "global from printGlobalText fun."
    print "var from printGlobalText: " + var

def printLocalText():
    #We are NOT telling to explicitly use the global version, so we are creating a local variable
    var = "local version from printLocalText fun"
    print "var from printLocalText: " + var

printGlobalText()
printLocalText()
"""
Output Result:
var from printGlobalText: global from printGlobalText fun.
var from printLocalText: local version from printLocalText
[Finished in 0.1s]
"""
 20
Author: Mohamed El-Saka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-04 18:45:42

To, co mówisz, to użycie takiej metody:

globvar = 5

def f():
    var = globvar
    print(var)

f()  # Prints 5

Ale lepszym sposobem jest użycie zmiennej globalnej w ten sposób:

globavar = 5
def f():
    global globvar
    print(globvar)
f()   #prints 5

Oba dają ten sam wynik.

 20
Author: gxyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-24 06:25:26

Jak się okazuje, odpowiedź jest zawsze prosta.

Oto mały przykładowy moduł z prostym sposobem pokazania go w definicji main:

def five(enterAnumber,sumation):
    global helper
    helper  = enterAnumber + sumation

def isTheNumber():
    return helper

Oto Jak to pokazać w definicji main:

import TestPy

def main():
    atest  = TestPy
    atest.five(5,8)
    print(atest.isTheNumber())

if __name__ == '__main__':
    main()

Ten prosty kod działa tak samo i zostanie wykonany. Mam nadzieję, że to pomoże.

 19
Author: user2876408,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-28 11:34:54

W rzeczywistości nie przechowujesz globalnego w zmiennej lokalnej, po prostu tworzysz lokalne odniesienie do tego samego obiektu, do którego odnosi się oryginalne globalne odniesienie. Pamiętaj, że prawie wszystko w Pythonie jest nazwą odnoszącą się do obiektu i nic nie jest kopiowane w zwykłej operacji.

Jeśli nie musisz jawnie określać, kiedy identyfikator ma odnosić się do predefiniowanego globalnego, prawdopodobnie musisz jawnie określić, kiedy identyfikator jest nową zmienną lokalną (na przykład z czymś w rodzaju polecenia ' var ' widocznego w JavaScript). Ponieważ zmienne lokalne są bardziej powszechne niż zmienne globalne w jakimkolwiek poważnym i nietrywialnym systemie, System Pythona ma większy sens w większości przypadków.

Ty mógłbyś mieć język, który próbował odgadnąć, używając zmiennej globalnej, gdyby istniała, lub tworząc zmienną lokalną, gdyby nie istniała. jednak byłoby to bardzo podatne na błędy. Na przykład importowanie innego modułu może nieumyślnie wprowadzić globalny zmienna o tej nazwie, zmieniająca zachowanie programu.

 18
Author: Kylotan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-30 21:09:51

Spróbuj tego:

def x1():
    global x
    x = 6

def x2():
    global x
    x = x+1
    print x

x = 5
x1()
x2()  # output --> 7
 15
Author: Sagar Mehta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-20 21:55:48

Następnie i jako dodatek, użyj pliku zawierającego wszystkie zmienne globalne zadeklarowane lokalnie, a następnie 'Importuj jako':

Plik initval.py

Stocksin = 300
Prices = []

Plik getstocks.py

import  initval as  iv

Def   getmystocks (): 
     iv.Stocksin  = getstockcount ()


Def getmycharts ():
    For ic in range (0,iv.Stocksin):

.....

 12
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-04 22:03:12

Pisanie do jawnych elementów globalnej tablicy nie wymaga deklaracji globalnej, choć pisanie do niej "hurtowo"ma taki wymóg:

import numpy as np

hostValue = 3.14159
hostArray = np.array([2., 3.])
hostMatrix = np.array([[1.0, 0.0],[ 0.0, 1.0]])

def func1():
    global hostValue    # mandatory, else local.
    hostValue = 2.0

def func2():
    global hostValue    # mandatory, else UnboundLocalError.
    hostValue += 1.0

def func3():
    global hostArray    # mandatory, else local.
    hostArray = np.array([14., 15.])

def func4():            # no need for globals
    hostArray[0] = 123.4

def func5():            # no need for globals
    hostArray[1] += 1.0

def func6():            # no need for globals
    hostMatrix[1][1] = 12.

def func7():            # no need for globals
    hostMatrix[0][0] += 0.33

func1()
print "After func1(), hostValue = ", hostValue
func2()
print "After func2(), hostValue = ", hostValue
func3()
print "After func3(), hostArray = ", hostArray
func4()
print "After func4(), hostArray = ", hostArray
func5()
print "After func5(), hostArray = ", hostArray
func6()
print "After func6(), hostMatrix = \n", hostMatrix
func7()
print "After func7(), hostMatrix = \n", hostMatrix
 11
Author: Mike Lampton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-08 22:35:22

Jeśli masz zmienną lokalną o tej samej nazwie, możesz użyć globals() function .

globals()['your_global_var'] = 42
 9
Author: Martin Thoma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-07 19:15:55

Odwołaj się do przestrzeni nazw klasy, w której ma się pojawić zmiana.

W tym przykładzie runner używa max z pliku config. Chcę, aby mój test zmienił wartość max , gdy runner go używa.

Main/config.py

max = 15000

Main/runner.py

from main import config
def check_threads():
    return max < thread_count 

Tests/runner_test.py

from main import runner                # <----- 1. add file
from main.runner import check_threads
class RunnerTest(unittest):
   def test_threads(self):
       runner.max = 0                  # <----- 2. set global 
       check_threads()
 5
Author: llewellyn falco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-19 08:48:27

Dodaję to, ponieważ nie widziałem tego w żadnej z innych odpowiedzi i może się to przydać komuś, kto zmaga się z czymś podobnym. Funkcja globals () zwraca zmienny globalny Słownik symboli, w którym można "magicznie" udostępniać dane dla reszty kodu. Na przykład:

from pickle import load
def loaditem(name):
    with open(r"C:\pickle\file\location"+"\{}.dat".format(name), "rb") as openfile:
        globals()[name] = load(openfile)
    return True

I

from pickle import dump
def dumpfile(name):
    with open(name+".dat", "wb") as outfile:
        dump(globals()[name], outfile)
    return True

Pozwoli Ci po prostu zrzucić / załadować zmienne Z i do globalnej przestrzeni nazw. Super wygodny, bez szumu, bez zamieszania. Jestem pewien, że to tylko python 3.

 5
Author: Rafaël Dera,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-05 14:59:14