Pergunta

Estou tendo problemas terríveis tentando entender regras de escopo em Python.

Com o seguinte script:

a = 7

def printA():
    print "Value of a is %d" % (a)

def setA(value):
    a = value
    print "Inside setA, a is now %d" %(a)


print "Before setA"
printA()
setA(42)
print "After setA"
printA()

Dá o inesperado (para mim) de saída de:

    Before setA
    Value of a is 7
    Inside setA, a is now 42
    After setA
    Value of a is 7

Onde eu esperaria a última impressão do valor de um ser 42, não 7. O que estou ausente sobre as regras de escopo em Python para o escopo de variáveis ??globais?

Foi útil?

Solução

As variáveis ??globais são especiais. Se você tentar atribuir a um dentro a = value variável de uma função, ele cria uma nova variável local dentro da função, mesmo se há uma variável global com o mesmo nome. Para vez acessar a variável global, adicionar um global declaração dentro do função:

a = 7
def setA(value):
    global a   # declare a to be a global
    a = value  # this sets the global value of a

Veja também Naming e vinculativa para uma explicação detalhada de do Python nomenclatura e regras vinculativas.

Outras dicas

O truque para entender isso é que quando você atribuir a uma variável, usando =, você também declará-lo como uma variável local. Então, ao invés de mudar o valor da variável de uma global, setA (valor) realmente define uma variável local (que passa a ser chamado de um) para o valor passado.

Isso se torna mais evidente se você tentar imprimir o valor de uma no início do setA (valor) assim:

def setA(value):
    print "Before assignment, a is %d" % (a)
    a = value
    print "Inside setA, a is now %d" % (a)

Se você tentar executar este Python lhe dará um erro útil:

Traceback (most recent call last):
  File "scopeTest.py", line 14, in 
    setA(42)
  File "scopeTest.py", line 7, in setA
    print "Before assignment, a is %d" % (a)
UnboundLocalError: local variable 'a' referenced before assignment

Isso nos diz que Python decidiu que a função setA (valor) tem uma variável local chamado, que é o que você alterar quando você atribui a ele na função. Se você não atribuir a um na função (como acontece com printa ()), então Python usa a variável A global.

Para marcar uma variável como global, você precisa usar a palavra-chave global em Python, no escopo que deseja usar a variável global . Neste caso, que está dentro da função setA (valor). Então, o script torna-se:

a = 7

def printA():
    print "Value of a is %d" % (a)

def setA(value):
    global a
    a = value
    print "Inside setA, a is now %d" %(a)


print "Before setA"
printA()
setA(42)
print "After setA"
printA()

Esta adição linha diz ao Python que quando você usa a variável a na função setA (valor) que você está falando sobre a variável global, não uma variável local.

Python não tem um conceito de variáveis ??como outras línguas. Você tem objetos que estão "em algum lugar" e você tem referências a esses objetos. = É usado para atribuir esses objetos para referências no atual namespace.

Você cria um nome um no espaço de nomes da função setA que se refere ao objeto ao qual o valor se refere.

dentro da função, a é tratado como uma variável local, você precisa definir

a global

dentro da função

A execução de uma função introduz uma nova tabela de símbolos utilizada para as variáveis ??locais da função. Mais precisamente, todas as atribuições de variáveis ??em uma função de armazenar o valor na tabela de símbolos local; enquanto referências de variáveis ??primeiro olhar na tabela de símbolos local, em seguida, nas tabelas de símbolos locais de funções que encerram, em seguida, na tabela de símbolos global e finalmente na tabela de nomes embutido. Assim, as variáveis ??globais não podem ser atribuídos diretamente um valor dentro de uma função (a menos que o nome em uma declaração global), embora possam ser referenciado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top