Uso da palavra-chave "global" em Python

285

O que eu entendo ao ler a documentação é que o Python tem um espaço para nome separado para funções e, se eu quiser usar uma variável global nessa função, preciso usá-lo global.

Estou usando o Python 2.7 e tentei este pequeno teste

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

Parece que as coisas estão funcionando bem, mesmo sem global. Consegui acessar a variável global sem nenhum problema.

Estou faltando alguma coisa? Além disso, a seguir é da documentação do Python:

Os nomes listados em uma instrução global não devem ser definidos como parâmetros formais ou em um destino de controle de loop for, definição de classe, definição de função ou instrução de importação.

Embora os parâmetros formais e a definição de classe façam sentido para mim, não consigo entender a restrição de destino de controle de loop e definição de função.

nik
fonte
1
Eu acho que você está confuso com php que exige o uso da palavra-chave global - os docs python confirmar isso - basicamente, se não for definido no contexto local é tratada como globais
tobyodavies
11
Tenha cuidado com sua redação: Python não possui um espaço para nome separado para funções (isso significaria que você poderia ter def foo(): ...e foo = ...ao mesmo tempo). Ele cria um novo escopo para cada chamada de função. (Mas como isso é diferente de todos os outros linguagem remotamente de alto nível no mundo?)

Respostas:

366

A palavra global- chave é útil apenas para alterar ou criar variáveis ​​globais em um contexto local, embora a criação de variáveis ​​globais raramente seja considerada uma boa solução.

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

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

O exposto acima lhe dará:

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

Embora se você usar a globalinstrução, a variável ficará disponível "fora" do escopo da função, tornando-se efetivamente uma variável global.

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

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

Portanto, o código acima fornecerá a você:

locally defined
locally defined

Além disso, devido à natureza do python, você também pode usar globalpara declarar funções, classes ou outros objetos em um contexto local. Embora eu desaconselhe, pois causa pesadelos se algo der errado ou precisar de depuração.

unode
fonte
59
"global" neste contexto parece ser diferente de outros idiomas, considere "global". No Python, uma referência "global" ainda está nos limites do módulo e precisaria ser referenciada de fora desse módulo como "module.global_var" em vez de simplesmente "global_var", como se poderia esperar.
juice
17
@ junice - No Python não existe absoluto globalsdefinido automaticamente em todos os namespaces (felizmente). Como você apontou corretamente, um global é vinculado a um espaço para nome em um módulo, no entanto, pode ser importado para outro módulo como from module import variableou import module.variable. No primeiro caso, a importação tornaria a variável acessível como variablesem exigir referência como module.. Se for considerado global no escopo do módulo, dependerá de onde é importado. Veja também nonlocalcomo uma nova palavra-chave relacionada ao escopo no python 3.
unode 16/10
3
Você poderia explicar por que variáveis ​​globais não são uma boa solução? Costumo ouvir isso, mas no meu projeto atual eles parecem fazer exatamente o que eu preciso que eles façam. Existe algo mais sinistro que eu não pensei?
Robin Newhouse
5
@RobinNewhouse Há algumas perguntas sobre o SO que já abordam esse tópico e outros artigos que não são do SO .
unode 18/10/13
213

Embora você possa acessar variáveis ​​globais sem a globalpalavra - chave, se você quiser modificá-las, precisará usar a globalpalavra - chave. Por exemplo:

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

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

No seu caso, você está apenas acessando a lista sub.

Ivo Wetzel
fonte
3
Com uma ressalva: foo = 3sem trabalhos globais, mas foo é definido novamente localmente no blubescopo da função e não modifica a variável foo original. Isso foi bastante confuso para mim.
chhantyal
1
@chhantyal if by works, você quer dizer que não gera um erro, você está correto, mas no contexto de Ivo Wetzel, ele não funcionaria como pretendido. Existem usos para esse comportamento, mas geralmente não é o que o programador deseja.
Democidist
77

Essa é a diferença entre acessar o nome e vinculá- lo a um escopo.

Se você está apenas procurando uma variável para ler seu valor, tem acesso ao escopo global e local.

No entanto, se você atribuir a uma variável cujo nome não esteja no escopo local, vincule esse nome a esse escopo (e se esse nome também existir como global, você o ocultará).

Se você deseja atribuir ao nome global, é necessário dizer ao analisador para usar o nome global em vez de vincular um novo nome local - que é o que a palavra-chave 'global' faz.

A vinculação em qualquer lugar dentro de um bloco faz com que o nome em qualquer parte desse bloco seja vinculado, o que pode causar algumas conseqüências de aparência bastante estranha (por exemplo, UnboundLocalError aparecendo repentinamente no código que estava funcionando anteriormente).

>>> 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
fonte
muito contraditório, difícil de acreditar que este é o código python válidos
PlsWork
52

As outras respostas respondem à sua pergunta. Outra coisa importante a saber sobre nomes em Python é que eles são locais ou globais em uma base por escopo.

Considere isso, por exemplo:

value = 42

def doit():
    print value
    value = 0

doit()
print value

Você provavelmente pode adivinhar que a value = 0instrução será atribuída a uma variável local e não afetará o valor da mesma variável declarada fora da doit()função. Você pode se surpreender ao descobrir que o código acima não será executado. A declaraçãoprint value dentro da função produz umUnboundLocalError.

O motivo é que o Python percebeu que, em outro lugar da função, você atribui o nome valuee também valuenão é declarado em nenhum lugar global. Isso a torna uma variável local. Mas quando você tenta imprimi-lo, o nome do local ainda não foi definido. O Python, nesse caso , não volta a procurar o nome como uma variável global, como algumas outras linguagens. Essencialmente, você não pode acessar uma variável global se tiver definido uma variável local com o mesmo nome em qualquer lugar da função.

kindall
fonte
1
Obrigado por apontar isso. Portanto, desde que seu escopo local não seja atribuído a um nome que exista fora dele, as referências no escopo local usarão o nome externo. No entanto, se em qualquer lugar da sua função você atribuir a esse nome, as referências nesse escopo local, mesmo antes da atribuição local, não serão exibidas fora.
Dmitry Minkovsky
1
Exatamente, você entendeu. global(ou nonlocalno Python 3.x) substitui esse comportamento e permite que você atribua novamente o nome externo.
Kindall
2
Em outras línguas, este parece ser referido como "elevação", como esta, por exemplo: github.com/shichuan/javascript-patterns/blob/master/...
Dmitry Minkovsky
Para adicionar insulto à lesão, as variáveis ​​declaradas com a palavra-chave JavaScript mais recente nãolet são hasteadas.
Kindall
É mais rápido acessar uma variável global declarada com globalou não importa?
mato
14

Acessar um nome e atribuir um nome são diferentes. No seu caso, você está apenas acessando um nome.

Se você atribuir a uma variável dentro de uma função, essa variável será assumida como local, a menos que você a declare global. Na ausência disso, supõe-se que seja global.

>>> 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
user225312
fonte
7
  • Você pode acessar palavras-chave globais sem palavra-chave global
  • Para poder modificá-los, você precisa declarar explicitamente que a palavra-chave é global. Caso contrário, a palavra-chave será declarada no escopo local.

Exemplo:

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]
mártires
fonte
2

Qualquer variável declarada fora de uma função é assumida como global; é somente ao declará-la de dentro de funções (exceto construtores) que você deve especificar que a variável seja global.

Jesus Ramos
fonte
1

Isso é explicado bem nas Perguntas frequentes do Python

Quais são as regras para variáveis ​​locais e globais no Python?

No Python, variáveis ​​referenciadas apenas dentro de uma função são implicitamente globais. Se uma variável tiver um valor atribuído em qualquer lugar do corpo da função, ela será considerada local, a menos que seja explicitamente declarada global.

Embora um pouco surpreendente a princípio, um momento de consideração explica isso. Por um lado, a exigência globalde variáveis ​​atribuídas fornece uma barreira contra efeitos colaterais indesejados. Por outro lado, se globalfosse necessário para todas as referências globais, você estaria usando globalo tempo todo. Você teria que declarar como globaltodas as referências a uma função interna ou a um componente de um módulo importado. Essa desordem anularia a utilidade da globaldeclaração para identificar efeitos colaterais.

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

user7610
fonte
0

Isso significa que você não deve fazer o seguinte:

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
fonte
O ikostia está enumerando todas as coisas que você não pode usar 'x' por ter usado global - docs.python.org/reference/…
pycruft
1
@Unode: Estou apenas demonstrando todos os casos que NikhilRathod deu em sua citação.
Ikostia
0

Global torna a variável "Global"

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


out()

print (x)

Isso faz com que 'x' atue como uma variável normal fora da função. Se você retirasse o global, isso causaria um erro, pois não pode imprimir uma variável dentro de uma função.

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
fonte