Можно ли обновить какой-либо из них в Python 3 и действительно ли скрипт работает?
Чарли Паркер
Ответы:
173
Каждый из них возвращает словарь:
globals()всегда возвращает словарь пространства имен модуля
locals()всегда возвращает в словарь в текущем пространстве имен
vars()возвращается либо в словаре текущего пространства имен (если вызывается без аргументов) , или в словаре аргумента.
localsи varsмог бы использовать еще несколько объяснений. Если locals()вызывается внутри функции, он обновляет dict значениями текущего пространства имен локальной переменной (плюс любые переменные замыкания) на тот момент и возвращает его. Несколько вызовов locals()в одном и том же фрейме стека каждый раз возвращают один и тот же dict - он присоединяется к объекту фрейма стека в качестве его f_localsатрибута. Содержимое диктовки обновляется при каждом locals()вызове и каждом f_localsдоступе к атрибуту, но только при таких вызовах или доступах к атрибутам. Он не обновляется автоматически при назначении переменных, и назначение записей в dict не будет назначать соответствующие локальные переменные:
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()
дает нам:
{'x':1}{'x':1,'l':{...}}212322
Первый print(l)показывает только 'x'запись, потому что назначение lпроисходит после locals()вызова. Второй print(l)после locals()повторного вызова показывает lзапись, хотя мы не сохранили возвращаемое значение. Третий и четвертый printэтапы показывают, что присвоение переменных не обновляется, lи наоборот, но после того, как мы f_localsполучили доступ , локальные переменные копируются locals()снова.
Две заметки:
Это поведение специфично для CPython - другие Pythons могут разрешать обновлениям автоматически возвращаться в локальное пространство имен.
В CPython 2.x это можно сделать, поместив exec "pass"строку в функцию. Это переключает функцию в более старый, более медленный режим выполнения, который использует locals()dict как каноническое представление локальных переменных.
Если locals()вызывается вне функции, он возвращает фактический словарь, который является текущим пространством имен. Дальнейшие изменения в пространстве имен будут отражены в словаре, и изменения в словаре будут отражены в пространстве имен:
classTest(object):
a ='one'
b ='two'
huh = locals()
c ='three'
huh['d']='four'print huh
Пока что все, о чем я говорил, locals()также верно для vars()... вот в чем разница: vars()принимает один объект в качестве аргумента, и если вы даете ему объект, он возвращает значение __dict__этого объекта. Для типичного объекта __dict__именно там хранится большая часть его атрибутных данных. Это включает переменные класса и глобальные переменные модуля:
classTest(object):
a ='one'
b ='two'def frobber(self):print self.c
t =Test()
huh = vars(t)
huh['c']='three'
t.frobber()
что дает нам:
three
Обратите внимание, что функция - __dict__это пространство имен ее атрибутов, а не локальные переменные. Для функций не имеет смысла __dict__хранить локальные переменные, поскольку рекурсия и многопоточность означают, что может быть несколько вызовов функции одновременно, каждый из которых имеет свои собственные локальные переменные:
Здесь fвызывает себя рекурсивно, поэтому внутренние и внешние вызовы перекрываются. Каждый из них видит свои локальные переменные при вызове locals(), но оба вызова видят одно f.__dict__и то же , и в нем f.__dict__нет локальных переменных.
Часть «и любые назначения словарю не отражаются в фактическом локальном пространстве имен» может быть сформулирована немного определенно .
Свен Марнач
Как ни странно, вы можете получить доступ к переменным, добавленным в vars()или locals()словарь, вызываемый внутри функции, если вы используете eval(). EG: def test(): huh = locals(); huh['d'] = 4; print eval('d')печатает 4, когда test()выполняется!
Марк Микофски
1
На самом деле назначение dict(возвращаемое locals()) оказывается отраженным в локальном пространстве имен, а изменения в локальном пространстве имен отражаются в dict(в моем python). Единственное, что спецификация не гарантирует такое поведение.
Скайкинг
Использование области имен термина выглядит для меня более легким, чем пространство имен .
сверхобмена
1
@overexchange: import thisи в Googlesite:docs.python.org namespace
Ответы:
Каждый из них возвращает словарь:
globals()
всегда возвращает словарь пространства имен модуляlocals()
всегда возвращает в словарь в текущем пространстве именvars()
возвращается либо в словаре текущего пространства имен (если вызывается без аргументов) , или в словаре аргумента.locals
иvars
мог бы использовать еще несколько объяснений. Еслиlocals()
вызывается внутри функции, он обновляет dict значениями текущего пространства имен локальной переменной (плюс любые переменные замыкания) на тот момент и возвращает его. Несколько вызововlocals()
в одном и том же фрейме стека каждый раз возвращают один и тот же dict - он присоединяется к объекту фрейма стека в качестве егоf_locals
атрибута. Содержимое диктовки обновляется при каждомlocals()
вызове и каждомf_locals
доступе к атрибуту, но только при таких вызовах или доступах к атрибутам. Он не обновляется автоматически при назначении переменных, и назначение записей в dict не будет назначать соответствующие локальные переменные:дает нам:
Первый
print(l)
показывает только'x'
запись, потому что назначениеl
происходит послеlocals()
вызова. Второйprint(l)
послеlocals()
повторного вызова показываетl
запись, хотя мы не сохранили возвращаемое значение. Третий и четвертыйprint
этапы показывают, что присвоение переменных не обновляется,l
и наоборот, но после того, как мыf_locals
получили доступ , локальные переменные копируютсяlocals()
снова.Две заметки:
exec "pass"
строку в функцию. Это переключает функцию в более старый, более медленный режим выполнения, который используетlocals()
dict как каноническое представление локальных переменных.Если
locals()
вызывается вне функции, он возвращает фактический словарь, который является текущим пространством имен. Дальнейшие изменения в пространстве имен будут отражены в словаре, и изменения в словаре будут отражены в пространстве имен:дает нам:
Пока что все, о чем я говорил,
locals()
также верно дляvars()
... вот в чем разница:vars()
принимает один объект в качестве аргумента, и если вы даете ему объект, он возвращает значение__dict__
этого объекта. Для типичного объекта__dict__
именно там хранится большая часть его атрибутных данных. Это включает переменные класса и глобальные переменные модуля:что дает нам:
Обратите внимание, что функция -
__dict__
это пространство имен ее атрибутов, а не локальные переменные. Для функций не имеет смысла__dict__
хранить локальные переменные, поскольку рекурсия и многопоточность означают, что может быть несколько вызовов функции одновременно, каждый из которых имеет свои собственные локальные переменные:что дает нам:
Здесь
f
вызывает себя рекурсивно, поэтому внутренние и внешние вызовы перекрываются. Каждый из них видит свои локальные переменные при вызовеlocals()
, но оба вызова видят одноf.__dict__
и то же , и в немf.__dict__
нет локальных переменных.источник
vars()
илиlocals()
словарь, вызываемый внутри функции, если вы используетеeval()
. EG:def test(): huh = locals(); huh['d'] = 4; print eval('d')
печатает 4, когдаtest()
выполняется!dict
(возвращаемоеlocals()
) оказывается отраженным в локальном пространстве имен, а изменения в локальном пространстве имен отражаются вdict
(в моем python). Единственное, что спецификация не гарантирует такое поведение.import this
и в Googlesite:docs.python.org namespace