Dado o seguinte código:
def A() :
b = 1
def B() :
# I can access 'b' from here.
print( b )
# But can i modify 'b' here? 'global' and assignment will not work.
B()
A()
Pois o código na B()
variável de função b
está no escopo externo, mas não no escopo global. É possível modificar a b
variável de dentro da B()
função? Certamente posso ler daqui e print()
, mas como modificá-lo?
python
python-2.7
Grigoryvp
fonte
fonte
b
seja mutável. Uma atribuição parab
mascarará o escopo externo.nonlocal
não foi retransmitido para 2.x. É uma parte intrínseca do suporte de fechamento.Respostas:
Python 3.x contém a
nonlocal
palavra - chave . Acho que isso faz o que você deseja, mas não tenho certeza se você está executando o python 2 ou 3.Para Python 2, geralmente uso apenas um objeto mutável (como uma lista ou dict) e altero o valor em vez de reatribuir.
exemplo:
Saídas:
fonte
class nonlocal: pass
no escopo externo. Em seguida,nonlocal.x
pode ser atribuído no escopo interno.SyntaxError
. TalvezNonLocal
?Nonlocal
? :-)Você pode usar uma classe vazia para manter um escopo temporário. É como o mutável, mas um pouco mais bonito.
Isso produz a seguinte saída interativa:
fonte
Sou um pouco novo em Python, mas li um pouco sobre isso. Acredito que o melhor que você conseguirá será semelhante à solução alternativa do Java, que consiste em agrupar sua variável externa em uma lista.
Edit: Eu acho que isso provavelmente era verdade antes do Python 3. Parece que
nonlocal
é sua resposta.fonte
Não, você não pode, pelo menos desta forma.
Porque a "operação de definição" criará um novo nome no escopo atual, que abrange o externo.
fonte
Para qualquer um que olhe para isso muito mais tarde, uma solução alternativa mais segura, porém mais pesada, é. Sem necessidade de passar variáveis como parâmetros.
fonte
A resposta curta que funcionará de forma automática e mágica
Criei uma biblioteca python para resolver esse problema específico. Ele é liberado sob a ausência de luz, então use-o como quiser. Você pode instalá-lo
pip install seapie
ou verificar a página inicial aqui https://github.com/hirsimaki-markus/SEAPIEuser@pc:home$ pip install seapie
saídas
os argumentos têm o seguinte significado:
B()
, 1 significaria paiA()
e 2 significaria avô<module>
também conhecido como globalA longa resposta
Isso é mais complicado. Seapie trabalha editando os quadros na pilha de chamadas usando CPython api. CPython é o padrão de fato, então a maioria das pessoas não precisa se preocupar com isso.
As palavras mágicas nas quais você provavelmente está interessado se estiver lendo isto são as seguintes:
O último forçará as atualizações a passarem para o escopo local. escopos locais são, entretanto, otimizados de maneira diferente do escopo global, portanto, introduzir novos objetos tem alguns problemas quando você tenta chamá-los diretamente, se eles não forem inicializados de alguma forma. Vou copiar algumas maneiras de contornar esses problemas da página do github
Se você acha que usar
exec()
não é algo que deseja acompanhar, pode emular o comportamento atualizando o dicionário local verdadeiro (não aquele retornado por locals ()). Vou copiar um exemplo de https://faster-cpython.readthedocs.io/mutable.htmlResultado:
fonte
Eu não acho que você deveria querer fazer isso. Funções que podem alterar coisas em seu contexto envolvente são perigosas, pois esse contexto pode ser escrito sem o conhecimento da função.
Você poderia torná-lo explícito, tornando B um método público e C um método privado em uma classe (provavelmente a melhor maneira); ou usando um tipo mutável, como uma lista, e passando-o explicitamente para C:
fonte
nonlocal
palavra-chave - mas depende de você usá-lo com muito cuidado.Você pode, mas terá que usar a instrução global (não é uma solução muito boa como sempre ao usar variáveis globais, mas funciona):
fonte
Não sei se existe um atributo de uma função que dá o
__dict__
do espaço exterior da função quando este espaço exterior não é o espaço global == o módulo, que é o caso quando a função é uma função aninhada, em Python 3.Mas em Python 2, até onde eu sei, não existe tal atributo.
Portanto, a única possibilidade de fazer o que você deseja é:
1) usando um objeto mutável, como dito por outros
2)
resultado
.
Nota
A solução de Cédric Julien tem uma desvantagem:
resultado
O b global após a execução de
A()
foi modificado e pode não ser desejadoEsse é o caso apenas se houver um objeto com o identificador b no namespace global
fonte