czy można zaktualizować którekolwiek z nich w Pythonie 3 i sprawić, by skrypt faktycznie działał?
Charlie Parker
Odpowiedzi:
172
Każdy z nich zwraca słownik:
globals()zawsze zwraca słownik przestrzeni nazw modułu
locals()Zawsze wraca do słownika bieżącej przestrzeni nazw
vars()powraca albo słownika bieżącej przestrzeni nazw (jeśli wywołana bez argumentów) lub w słowniku argumentu.
localsi varsprzydałoby się więcej wyjaśnień. Jeśli locals()jest wywoływana wewnątrz funkcji, aktualizuje dict o wartości bieżącej przestrzeni nazw zmiennej lokalnej (plus wszelkie zmienne zamykające) na ten moment i zwraca ją. Wielokrotne wywołania locals()w tej samej ramce stosu za każdym razem zwracają ten sam dykt - jest on dołączony do obiektu ramki stosu jako jego f_localsatrybut. Zawartość dyktu jest aktualizowana przy każdym locals()wywołaniu i każdym f_localsdostępie do atrybutu, ale tylko przy takich wywołaniach lub dostępach do atrybutów. Nie aktualizuje się automatycznie po przypisaniu zmiennych, a przypisanie wpisów w dict nie spowoduje przypisania odpowiednich zmiennych lokalnych:
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()
daje nam:
{'x':1}{'x':1,'l':{...}}212322
Pierwsza print(l)pokazuje tylko 'x'wpis, ponieważ przypisanie do lnastępuje po locals()wywołaniu. Drugi print(l), po locals()ponownym wywołaniu , pokazuje lwpis, mimo że nie zapisaliśmy wartości zwracanej. Trzeci i czwarty printpokazują, że przypisywanie zmiennych nie aktualizuje się li odwrotnie, ale po uzyskaniu dostępu f_localszmienne lokalne są locals()ponownie kopiowane do .
Dwie uwagi:
To zachowanie jest specyficzne dla CPythona - inne Pythony mogą zezwolić aktualizacjom na automatyczne przywrócenie lokalnej przestrzeni nazw.
W CPythonie 2.x można to zrobić, wstawiając exec "pass"linię do funkcji. Powoduje to przełączenie funkcji do starszego, wolniejszego trybu wykonywania, w którym locals()dict jest kanoniczną reprezentacją zmiennych lokalnych.
Jeśli locals()jest wywoływana poza funkcją, zwraca rzeczywisty słownik, który jest bieżącą przestrzenią nazw. Dalsze zmiany w przestrzeni nazw są odzwierciedlane w słowniku, a zmiany w słowniku są odzwierciedlane w przestrzeni nazw:
classTest(object):
a ='one'
b ='two'
huh = locals()
c ='three'
huh['d']='four'print huh
Jak dotąd wszystko, o czym powiedziałem, locals()odnosi się również do vars()... oto różnica: vars()przyjmuje pojedynczy obiekt jako swój argument, a jeśli dasz mu obiekt, zwraca wartość __dict__tego obiektu. W przypadku typowego obiektu __dict__jest to miejsce, w którym przechowywana jest większość danych atrybutów. Obejmuje to zmienne klas i globalne modułów:
classTest(object):
a ='one'
b ='two'def frobber(self):print self.c
t =Test()
huh = vars(t)
huh['c']='three'
t.frobber()
co daje nam:
three
Zauważ, że funkcja __dict__jest przestrzenią nazw atrybutu, a nie zmiennymi lokalnymi. __dict__Przechowywanie zmiennych lokalnych przez funkcję nie miałoby sensu , ponieważ rekurencja i wielowątkowość oznaczają, że w tym samym czasie może istnieć wiele wywołań funkcji, każde z własnymi lokalnymi:
Tutaj fwywołuje się rekurencyjnie, więc wewnętrzne i zewnętrzne wywołania nakładają się. Każdy z nich widzi swoje własne zmienne lokalne podczas wywołania locals(), ale oba wywołania widzą to samof.__dict__ i f.__dict__nie mają żadnych zmiennych lokalnych.
Część „i wszelkie przypisania do słownika nie są odzwierciedlane w rzeczywistej lokalnej przestrzeni nazw” mogą być sformułowane nieco zbyt jasno .
Sven Marnach
Co dziwne, jeśli używasz, możesz uzyskać dostęp do zmiennych dodanych do słownika vars()lub locals()wywoływanego w funkcji eval(). EG: wyświetla def test(): huh = locals(); huh['d'] = 4; print eval('d')4 po test()wykonaniu!
Mark Mikofski
1
W rzeczywistości przypisanie do dict(zwrócone przez locals()) jest odzwierciedlane w lokalnej przestrzeni nazw, a zmiany w lokalnej przestrzeni nazw są odzwierciedlane w dict(w moim Pythonie). Tyle tylko, że specyfikacja nie gwarantuje takiego zachowania.
jazda na nartach
Użycie zakresu nazw terminów wygląda dla mnie łatwiej niż przestrzeń nazw .
przewyższenie
1
@overexchange: import thisoraz w Googlesite:docs.python.org namespace
Odpowiedzi:
Każdy z nich zwraca słownik:
globals()
zawsze zwraca słownik przestrzeni nazw modułulocals()
Zawsze wraca do słownika bieżącej przestrzeni nazwvars()
powraca albo słownika bieżącej przestrzeni nazw (jeśli wywołana bez argumentów) lub w słowniku argumentu.locals
ivars
przydałoby się więcej wyjaśnień. Jeślilocals()
jest wywoływana wewnątrz funkcji, aktualizuje dict o wartości bieżącej przestrzeni nazw zmiennej lokalnej (plus wszelkie zmienne zamykające) na ten moment i zwraca ją. Wielokrotne wywołanialocals()
w tej samej ramce stosu za każdym razem zwracają ten sam dykt - jest on dołączony do obiektu ramki stosu jako jegof_locals
atrybut. Zawartość dyktu jest aktualizowana przy każdymlocals()
wywołaniu i każdymf_locals
dostępie do atrybutu, ale tylko przy takich wywołaniach lub dostępach do atrybutów. Nie aktualizuje się automatycznie po przypisaniu zmiennych, a przypisanie wpisów w dict nie spowoduje przypisania odpowiednich zmiennych lokalnych:daje nam:
Pierwsza
print(l)
pokazuje tylko'x'
wpis, ponieważ przypisanie dol
następuje polocals()
wywołaniu. Drugiprint(l)
, polocals()
ponownym wywołaniu , pokazujel
wpis, mimo że nie zapisaliśmy wartości zwracanej. Trzeci i czwartyprint
pokazują, że przypisywanie zmiennych nie aktualizuje sięl
i odwrotnie, ale po uzyskaniu dostępuf_locals
zmienne lokalne sąlocals()
ponownie kopiowane do .Dwie uwagi:
exec "pass"
linię do funkcji. Powoduje to przełączenie funkcji do starszego, wolniejszego trybu wykonywania, w którymlocals()
dict jest kanoniczną reprezentacją zmiennych lokalnych.Jeśli
locals()
jest wywoływana poza funkcją, zwraca rzeczywisty słownik, który jest bieżącą przestrzenią nazw. Dalsze zmiany w przestrzeni nazw są odzwierciedlane w słowniku, a zmiany w słowniku są odzwierciedlane w przestrzeni nazw:daje nam:
Jak dotąd wszystko, o czym powiedziałem,
locals()
odnosi się również dovars()
... oto różnica:vars()
przyjmuje pojedynczy obiekt jako swój argument, a jeśli dasz mu obiekt, zwraca wartość__dict__
tego obiektu. W przypadku typowego obiektu__dict__
jest to miejsce, w którym przechowywana jest większość danych atrybutów. Obejmuje to zmienne klas i globalne modułów:co daje nam:
Zauważ, że funkcja
__dict__
jest przestrzenią nazw atrybutu, a nie zmiennymi lokalnymi.__dict__
Przechowywanie zmiennych lokalnych przez funkcję nie miałoby sensu , ponieważ rekurencja i wielowątkowość oznaczają, że w tym samym czasie może istnieć wiele wywołań funkcji, każde z własnymi lokalnymi:co daje nam:
Tutaj
f
wywołuje się rekurencyjnie, więc wewnętrzne i zewnętrzne wywołania nakładają się. Każdy z nich widzi swoje własne zmienne lokalne podczas wywołanialocals()
, ale oba wywołania widzą to samof.__dict__
if.__dict__
nie mają żadnych zmiennych lokalnych.źródło
vars()
lublocals()
wywoływanego w funkcjieval()
. EG: wyświetladef test(): huh = locals(); huh['d'] = 4; print eval('d')
4 potest()
wykonaniu!dict
(zwrócone przezlocals()
) jest odzwierciedlane w lokalnej przestrzeni nazw, a zmiany w lokalnej przestrzeni nazw są odzwierciedlane wdict
(w moim Pythonie). Tyle tylko, że specyfikacja nie gwarantuje takiego zachowania.import this
oraz w Googlesite:docs.python.org namespace