pode-se atualizar qualquer um desses itens no python 3 e fazer com que o script realmente funcione?
Charlie Parker
Respostas:
172
Cada um deles retorna um dicionário:
globals()sempre retorna o dicionário do espaço para nome do módulo
locals()sempre retorna um dicionário do espaço para nome atual
vars()retorna um dicionário do espaço para nome atual (se chamado sem argumento) ou o dicionário do argumento.
localse varspoderia usar mais algumas explicações. Se locals()for chamado dentro de uma função, ele atualiza um ditado com os valores do namespace da variável local atual (mais quaisquer variáveis de fechamento) a partir desse momento e o retorna. Várias chamadas para locals()no mesmo quadro de pilha retornam o mesmo ditado toda vez - elas são anexadas ao objeto de quadro de pilha como seu f_localsatributo. O conteúdo do dict é atualizado em cada locals()chamada e f_localsacesso a cada atributo, mas apenas nessas chamadas ou acessos a atributos. Ele não é atualizado automaticamente quando variáveis são atribuídas, e a atribuição de entradas no dict não atribuirá as variáveis locais correspondentes:
import inspect
def f():
x =1
l = locals()print(l)
locals()print(l)
x =2print(x, l['x'])
l['x']=3print(x, l['x'])
inspect.currentframe().f_locals
print(x, l['x'])
f()
nos dá:
{'x':1}{'x':1,'l':{...}}212322
O primeiro print(l)mostra apenas uma 'x'entrada, porque a atribuição locorre após a locals()chamada. O segundo print(l), depois de ligar locals()novamente, mostra uma lentrada, mesmo que não tenhamos salvado o valor de retorno. O terceiro e o quarto prints mostram que a atribuição de variáveis não é atualizada le vice-versa, mas após o acesso f_locals, as variáveis locais são copiadas locals()novamente.
Duas notas:
Esse comportamento é específico do CPython - outros Pythons podem permitir que as atualizações retornem ao espaço de nomes local automaticamente.
No CPython 2.x, é possível fazer isso funcionar colocando uma exec "pass"linha na função. Isso muda a função para um modo de execução mais antigo e lento, que usa o locals()dict como representação canônica de variáveis locais.
Se locals()for chamado fora de uma função, ele retornará o dicionário real que é o espaço para nome atual. Outras alterações no espaço para nome são refletidas no dicionário e as alterações no dicionário são refletidas no espaço para nome:
classTest(object):
a ='one'
b ='two'
huh = locals()
c ='three'
huh['d']='four'print huh
Até agora, tudo o que eu disse locals()também é verdadeiro vars()... aqui está a diferença: vars()aceita um único objeto como argumento e, se você der um objeto, ele retorna o __dict__objeto. Para um objeto típico, __dict__é onde a maioria dos dados de atributo é armazenada. Isso inclui variáveis de classe e globais do módulo:
classTest(object):
a ='one'
b ='two'def frobber(self):print self.c
t =Test()
huh = vars(t)
huh['c']='three'
t.frobber()
o que nos dá:
three
Observe que a função __dict__é seu namespace de atributo, não variáveis locais. Não faria sentido para uma função __dict__armazenar variáveis locais, já que recursão e multithreading significam que pode haver várias chamadas para uma função ao mesmo tempo, cada uma com seus próprios locais:
Aqui, se fchama recursivamente, de modo que as chamadas internas e externas se sobrepõem. Cada um vê suas próprias variáveis locais quando chama locals(), mas as duas chamam o mesmo f.__dict__e f.__dict__não possuem nenhuma variável local.
A parte "e quaisquer atribuições ao dicionário não são refletidas no espaço de nome local real" pode ser redigida um pouco para definir .
Sven Marnach
Curiosamente, você pode acessar variáveis adicionadas a um vars()ou locals()dicionário chamado dentro de uma função, se você usar eval(). EG: def test(): huh = locals(); huh['d'] = 4; print eval('d')imprime 4 quando test()é executado!
Mark Mikofski
1
Na verdade, a atribuição ao dict(retornado por locals()) é refletida no espaço para nome local e as alterações no espaço para nome local são refletidas no dict(no meu python). A única coisa é que a especificação não garante esse comportamento.
skyking
O uso do escopo do nome do termo parece mais fácil para mim do que o namespace .
overexchange
1
@overexchange: import thise no googlesite:docs.python.org namespace
Respostas:
Cada um deles retorna um dicionário:
globals()
sempre retorna o dicionário do espaço para nome do módulolocals()
sempre retorna um dicionário do espaço para nome atualvars()
retorna um dicionário do espaço para nome atual (se chamado sem argumento) ou o dicionário do argumento.locals
evars
poderia usar mais algumas explicações. Selocals()
for chamado dentro de uma função, ele atualiza um ditado com os valores do namespace da variável local atual (mais quaisquer variáveis de fechamento) a partir desse momento e o retorna. Várias chamadas paralocals()
no mesmo quadro de pilha retornam o mesmo ditado toda vez - elas são anexadas ao objeto de quadro de pilha como seuf_locals
atributo. O conteúdo do dict é atualizado em cadalocals()
chamada ef_locals
acesso a cada atributo, mas apenas nessas chamadas ou acessos a atributos. Ele não é atualizado automaticamente quando variáveis são atribuídas, e a atribuição de entradas no dict não atribuirá as variáveis locais correspondentes:nos dá:
O primeiro
print(l)
mostra apenas uma'x'
entrada, porque a atribuiçãol
ocorre após alocals()
chamada. O segundoprint(l)
, depois de ligarlocals()
novamente, mostra umal
entrada, mesmo que não tenhamos salvado o valor de retorno. O terceiro e o quartoprint
s mostram que a atribuição de variáveis não é atualizadal
e vice-versa, mas após o acessof_locals
, as variáveis locais são copiadaslocals()
novamente.Duas notas:
exec "pass"
linha na função. Isso muda a função para um modo de execução mais antigo e lento, que usa olocals()
dict como representação canônica de variáveis locais.Se
locals()
for chamado fora de uma função, ele retornará o dicionário real que é o espaço para nome atual. Outras alterações no espaço para nome são refletidas no dicionário e as alterações no dicionário são refletidas no espaço para nome:nos dá:
Até agora, tudo o que eu disse
locals()
também é verdadeirovars()
... aqui está a diferença:vars()
aceita um único objeto como argumento e, se você der um objeto, ele retorna o__dict__
objeto. Para um objeto típico,__dict__
é onde a maioria dos dados de atributo é armazenada. Isso inclui variáveis de classe e globais do módulo:o que nos dá:
Observe que a função
__dict__
é seu namespace de atributo, não variáveis locais. Não faria sentido para uma função__dict__
armazenar variáveis locais, já que recursão e multithreading significam que pode haver várias chamadas para uma função ao mesmo tempo, cada uma com seus próprios locais:o que nos dá:
Aqui, se
f
chama recursivamente, de modo que as chamadas internas e externas se sobrepõem. Cada um vê suas próprias variáveis locais quando chamalocals()
, mas as duas chamam o mesmof.__dict__
ef.__dict__
não possuem nenhuma variável local.fonte
vars()
oulocals()
dicionário chamado dentro de uma função, se você usareval()
. EG:def test(): huh = locals(); huh['d'] = 4; print eval('d')
imprime 4 quandotest()
é executado!dict
(retornado porlocals()
) é refletida no espaço para nome local e as alterações no espaço para nome local são refletidas nodict
(no meu python). A única coisa é que a especificação não garante esse comportamento.import this
e no googlesite:docs.python.org namespace