Użycie słowa kluczowego „global” w Pythonie

285

Z lektury dokumentacji rozumiem, że Python ma osobną przestrzeń nazw dla funkcji i jeśli chcę użyć zmiennej globalnej w tej funkcji, muszę jej użyć global.

Używam Python 2.7 i próbowałem tego małego testu

>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
...     return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'

Wygląda na to, że wszystko działa dobrze nawet bez global. Byłem w stanie uzyskać dostęp do zmiennej globalnej bez żadnego problemu.

Czy coś mi brakuje? Ponadto, z dokumentacji Pythona:

Nazw wymienionych w instrukcji globalnej nie wolno definiować jako parametrów formalnych ani w celu kontroli pętli for, definicji klasy, definicji funkcji lub instrukcji importu.

Chociaż formalne parametry i definicja klasy mają dla mnie sens, nie jestem w stanie zrozumieć ograniczenia dotyczącego celu kontroli pętli i definicji funkcji.

nik
źródło
1
Myślę, że mylisz się z php, który wymaga użycia globalnego słowa kluczowego - docs docs docs docs - zasadniczo jeśli nie jest zdefiniowany w lokalnym kontekście, jest traktowany jako globalny
tobyodavies
11
Uważaj na swoje sformułowania: Python nie ma oddzielnej przestrzeni nazw dla funkcji (oznaczałoby to, że możesz mieć def foo(): ...i foo = ...jednocześnie). Tworzy nowy zakres dla każdego wywołania funkcji. (Ale czym to się różni od każdego innego zdalnie wysokiego poziomu języka na świecie?)

Odpowiedzi:

366

Słowo kluczowe globaljest przydatne tylko do zmiany lub tworzenia zmiennych globalnych w kontekście lokalnym, chociaż tworzenie zmiennych globalnych rzadko jest uważane za dobre rozwiązanie.

def bob():
    me = "locally defined"    # Defined only in local context
    print(me)

bob()
print(me)     # Asking for a global variable

Powyższe daje ci:

locally defined
Traceback (most recent call last):
  File "file.py", line 9, in <module>
    print(me)
NameError: name 'me' is not defined

Natomiast jeśli użyjesz globalinstrukcji, zmienna stanie się dostępna „poza” zakresem funkcji, skutecznie tworząc zmienną globalną.

def bob():
    global me
    me = "locally defined"   # Defined locally but declared as global
    print(me)

bob()
print(me)     # Asking for a global variable

Powyższy kod da ci:

locally defined
locally defined

Ponadto, ze względu na naturę Pythona, można również używać globaldo deklarowania funkcji, klas lub innych obiektów w kontekście lokalnym. Chociaż odradzałbym to, ponieważ powoduje koszmary, jeśli coś pójdzie nie tak lub wymaga debugowania.

unode
źródło
59
„globalny” w tym kontekście wydaje się różny od innych języków uznawanych za „globalny”. W Pythonie odwołanie „globalne” wciąż znajduje się w obrębie modułu i powinno być przywoływane z zewnątrz tego modułu jako „module.global_var”, a nie po prostu „global_var”, jak można się spodziewać.
sok
17
@juice - W Pythonie nie ma czegoś takiego jak absolut globalszdefiniowany automatycznie we wszystkich przestrzeniach nazw (na szczęście). Jak słusznie zauważyłeś, globalny jest powiązany z przestrzenią nazw w module, jednak można go zaimportować do innego modułu jako from module import variablelub import module.variable. W pierwszym przypadku import spowodowałby, że zmienna byłaby dostępna jako variablebez wymagania odniesienia jako module.. Jeśli zostanie uznany za globalny, zakres modułu zależy od tego, gdzie jest importowany. Zobacz także nonlocaljako nowe słowo kluczowe związane z zakresem w python 3.
unode
3
Czy możesz wyjaśnić, dlaczego zmienne globalne nie są dobrym rozwiązaniem? Często to słyszę, ale wydaje mi się, że w moim obecnym projekcie robią to, czego potrzebuję. Czy jest coś bardziej złowrogiego, o czym nie myślałem?
Robin Newhouse
5
@RobinNewhouse Jest kilka pytań na temat SO już na ten temat i inne artykuły, które nie są SO .
unode
213

Chociaż możesz uzyskać dostęp do zmiennych globalnych bez globalsłowa kluczowego, jeśli chcesz je zmodyfikować, musisz użyć globalsłowa kluczowego. Na przykład:

foo = 1
def test():
    foo = 2 # new local foo

def blub():
    global foo
    foo = 3 # changes the value of the global foo

W twoim przypadku po prostu uzyskujesz dostęp do listy sub.

Ivo Wetzel
źródło
3
Z jednym zastrzeżeniem: foo = 3bez globalnego działania, ale foo jest ponownie zdefiniowane lokalnie w blubzakresie funkcji i nie modyfikuje oryginalnej zmiennej foo. To było dla mnie dość mylące.
chhantyal
1
@chhantyal, jeśli przez prace rozumiesz, że nie powoduje to błędu, masz rację, ale w kontekście Ivo Wetzela nie działałoby to zgodnie z przeznaczeniem. Istnieją takie zastosowania, ale programista często nie chce tego.
democidysta
77

Jest to różnica między dostępem do nazwy a powiązaniem jej w zakresie.

Jeśli szukasz tylko zmiennej, aby odczytać jej wartość, masz dostęp do zasięgu globalnego i lokalnego.

Jeśli jednak przypiszesz zmienną, której nazwa nie jest w zasięgu lokalnym, wiążesz tę nazwę z tym zakresem (a jeśli ta nazwa istnieje również jako globalna, ukryjesz ją).

Jeśli chcesz mieć możliwość przypisania nazwy globalnej, musisz powiedzieć parserowi, aby używał nazwy globalnej, a nie przypisywać nową nazwę lokalną - to właśnie robi słowo kluczowe „global”.

Powiązanie w dowolnym miejscu bloku powoduje związanie nazwy w tym bloku, co może powodować dość dziwnie wyglądające konsekwencje (np. Niespodziewane pojawienie się UnboundLocalError we wcześniej działającym kodzie).

>>> a = 1
>>> def p():
    print(a) # accessing global scope, no binding going on
>>> def q():
    a = 3 # binding a name in local scope - hiding global
    print(a)
>>> def r():
    print(a) # fail - a is bound to local scope, but not assigned yet
    a = 4
>>> p()
1
>>> q()
3
>>> r()
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    r()
  File "<pyshell#32>", line 2, in r
    print(a) # fail - a is bound to local scope, but not assigned yet
UnboundLocalError: local variable 'a' referenced before assignment
>>> 
pycruft
źródło
bardzo sprzeczne z intuicją, trudno uwierzyć, że jest to poprawny kod Pythona
PlsWork
52

Inne odpowiedzi odpowiadają na twoje pytanie. Inną ważną rzeczą, którą należy wiedzieć o nazwach w Pythonie, jest to, że są one lokalne lub globalne dla poszczególnych zakresów.

Rozważ to, na przykład:

value = 42

def doit():
    print value
    value = 0

doit()
print value

Prawdopodobnie można się domyślić, że value = 0instrukcja zostanie przypisana do zmiennej lokalnej i nie wpłynie na wartość tej samej zmiennej zadeklarowanej poza doit()funkcją. Możesz być bardziej zaskoczony, gdy odkryjesz, że powyższy kod nie działa. Instrukcja print valuewewnątrz funkcji tworzyUnboundLocalError.

Powodem jest to, że Python zauważył, że gdzie indziej w funkcji przypisujesz nazwę value, a także valuenigdzie nie jest zadeklarowana global. To sprawia, że ​​jest to zmienna lokalna. Ale kiedy próbujesz go wydrukować, nazwa lokalna nie została jeszcze zdefiniowana. Python w tym przypadku nie wraca do szukania nazwy jako zmiennej globalnej, podobnie jak niektóre inne języki. Zasadniczo nie można uzyskać dostępu do zmiennej globalnej, jeśli zdefiniowano zmienną lokalną o tej samej nazwie w dowolnym miejscu funkcji.

kindall
źródło
1
Dzięki za zwrócenie na to uwagi. Tak więc, o ile zakres lokalny nie przypisuje nazwy, która istnieje poza nim, odwołania do zakresu lokalnego będą używać nazwy zewnętrznej. Jeśli jednak gdziekolwiek w funkcji przypisujesz tę nazwę, odniesienia w tym zasięgu lokalnym, nawet przed przypisaniem lokalnym, nie wyglądają na zewnątrz.
Dmitrij Minkowski
1
Dokładnie, masz to. global(lub nonlocalw Python 3.x) zastępuje to zachowanie i pozwala na ponowne przypisanie nazwy zewnętrznej.
uprzejmie
2
W innych językach wydaje się, że jest to nazywane „podnoszeniem”, na przykład: github.com/shichuan/javascript-patterns/blob/master/…
Dmitry Minkovsky
Aby dodać obrażenia do obrażeń, zmienne zadeklarowane przy użyciu nowszego słowa kluczowego JavaScript nielet są podnoszone.
kindall
Czy szybszy jest dostęp do zmiennej globalnej zadeklarowanej za pomocą, globalczy to nie ma znaczenia?
mato
14

Dostęp do nazwy i przypisanie nazwy są różne. W twoim przypadku po prostu uzyskujesz dostęp do nazwy.

Jeśli przypiszesz zmienną do funkcji, zakłada się, że zmienna ta jest lokalna, chyba że zadeklarujesz ją jako globalną. W przypadku braku tego zakłada się, że ma charakter globalny.

>>> x = 1         # global 
>>> def foo():
        print x       # accessing it, it is global

>>> foo()
1
>>> def foo():   
        x = 2        # local x
        print x 

>>> x            # global x
1
>>> foo()        # prints local x
2
użytkownik225312
źródło
7
  • Możesz uzyskać dostęp do globalnych słów kluczowych bez słowa kluczowego global
  • Aby móc je modyfikować, musisz wyraźnie stwierdzić, że słowo kluczowe ma charakter globalny. W przeciwnym razie słowo kluczowe zostanie zadeklarowane w zasięgu lokalnym.

Przykład:

words = [...] 

def contains (word): 
    global words             # <- not really needed
    return (word in words) 

def add (word): 
    global words             # must specify that we're working with a global keyword
    if word not in words: 
        words += [word]
martynas
źródło
2

Zakłada się, że każda zmienna zadeklarowana poza funkcją jest globalna, tylko wtedy, gdy deklaruje się ją z wnętrza funkcji (z wyjątkiem konstruktorów), należy określić, że zmienna jest globalna.

Jesus Ramos
źródło
1

Wyjaśniono to dobrze w FAQ Pythona

Jakie są reguły dla zmiennych lokalnych i globalnych w Pythonie?

W Pythonie zmienne, do których odwołuje się tylko funkcja, są domyślnie globalne. Jeśli zmienna ma przypisaną wartość w dowolnym miejscu w ciele funkcji, zakłada się, że jest ona lokalna, chyba że jest jawnie zadeklarowana jako globalna.

Choć na początku trochę zaskakujące, moment zastanowienia wyjaśnia to. Z jednej strony wymaganie globaldla przypisanych zmiennych zapewnia pasek przeciw niezamierzonym skutkom ubocznym. Z drugiej strony, gdyby globalbyło to wymagane dla wszystkich globalnych odniesień, będziesz używać globalcały czas. Będziesz musiał zadeklarować jako globalkażde odniesienie do wbudowanej funkcji lub komponentu importowanego modułu. Ten bałagan pokonałby przydatność globaldeklaracji do identyfikowania skutków ubocznych.

https://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python

użytkownik7610
źródło
0

Oznacza to, że nie powinieneś wykonywać następujących czynności:

x = 1

def myfunc():
  global x

  # formal parameter
  def localfunction(x):
    return x+1

  # import statement
  import os.path as x

  # for loop control target
  for x in range(10):
    print x

  # class definition
  class x(object):
    def __init__(self):
      pass

  #function definition
  def x():
    print "I'm bad"
ikostia
źródło
ikostia wylicza wszystkie rzeczy, których nie można użyć „x” za użycie globalne - docs.python.org/reference/…
pycruft 14.01.11
1
@Unode: Po prostu demonstruję wszystkie przypadki, które NikhilRathod podał w swoim cytacie.
ikostia
0

Globalny sprawia, że ​​zmienna „Globalna”

def out():
    global x
    x = 1
    print(x)
    return


out()

print (x)

To sprawia, że ​​„x” działa jak normalna zmienna poza funkcją. Jeśli wyjmiesz globalny, spowoduje to błąd, ponieważ nie może wydrukować zmiennej wewnątrz funkcji.

def out():
     # Taking out the global will give you an error since the variable x is no longer 'global' or in other words: accessible for other commands
    x = 1
    print(x)
    return


out()

print (x)
Michael
źródło