Подтвердить что ты не робот

Причина для globals() в Python?

В чем причина использования функции globals() в Python? Он только возвращает словарь глобальных переменных, которые уже являются глобальными, поэтому их можно использовать где угодно... Я спрашиваю только из любопытства, пытаясь узнать python.

def F():
    global x
    x = 1

def G():
    print(globals()["x"]) #will return value of global 'x', which is 1

def H():
    print(x) #will also return value of global 'x', which, also, is 1

F()
G()
H()

На самом деле я не вижу здесь смысла? Только время, в котором я нуждался, было, если бы у меня были локальные и глобальные переменные, с тем же именем для них обоих

def F():
    global x
    x = 1

def G():
    x = 5
    print(x) #5
    print(globals()["x"]) #1

F()
G()

Но вы никогда не должны сталкиваться с проблемой наличия двух переменных с одним и тем же именем и должны использовать их как в рамках одной области.

4b9b3361

Ответ 1

Python предоставляет программисту большое количество инструментов для изучения рабочей среды. globals() является лишь одним из них, и может оказаться очень полезным в сеансе отладки, чтобы увидеть, какие объекты фактически содержит глобальная область.

Обоснование этого, я уверен, такое же, как использование locals() для просмотра переменных, определенных в функции, или с помощью dir для просмотра содержимого модуля или атрибутов объект.

Исходя из фона С++, я могу понять, что эти вещи кажутся ненужными. В статически связанной, статически типизированной среде они абсолютно были бы. В этом случае во время компиляции известно, какие именно переменные являются глобальными, и какие элементы будут иметь объекты, и даже какие имена экспортируются другой единицей компиляции.

Однако на динамическом языке эти вещи не фиксированы; они могут меняться в зависимости от того, как импортируется код или даже во время выполнения. По этой причине, по крайней мере, доступ к этой информации в отладчике может быть неоценим.

Ответ 2

Это также полезно, когда вам нужно вызвать функцию, используя имя строки функции. Например:

def foo():
    pass

function_name_as_string = 'foo'

globals()[function_name_as_string]() # foo(). 

Ответ 3

Вы можете передать результат globals() и locals() в команды eval, execfile и __import__. Это создает ограниченную среду для работы этих команд.

Таким образом, эти функции существуют для поддержки других функций, которые получают выгоду от предоставления среды, потенциально отличной от текущего контекста. Например, вы можете вызвать globals(), а затем удалить или добавить некоторые переменные перед вызовом одной из этих функций.

Ответ 4

globals() полезен для eval() - если вы хотите оценить некоторый код, который ссылается на переменные в области видимости, эти переменные будут либо в глобальных или локальных.


Чтобы развернуть бит, встроенная функция eval() будет интерпретировать строку кода Python, предоставленную ей. Подпись: eval(codeString, globals, locals), и вы будете использовать ее так:

def foo():
    x = 2
    y = eval("x + 1", globals(), locals())
    print("y=" + y) # should be 3

Это работает, потому что интерпретатор получает значение x из locals() dict переменных. Вы можете, конечно, предоставить свой собственный параметр переменных для оценки.

Ответ 5

Это может быть полезно в "декларативном питоне". Например, ниже FooDef и BarDef являются классами, используемыми для определения серии структур данных, которые затем используются каким-то пакетом в качестве его ввода или его конфигурацией. Это позволяет вам много гибкости в том, что ваш вход, и вам не нужно писать парсер.

# FooDef, BarDef are classes

Foo_one = FooDef("This one", opt1 = False, valence = 3 )
Foo_two = FooDef("The other one", valence = 6, parent = Foo_one )

namelist = []
for i in range(6):
    namelist.append("nm%03d"%i)

Foo_other = FooDef("a third one", string_list = namelist )

Bar_thing = BarDef( (Foo_one, Foo_two), method = 'depth-first')

Обратите внимание, что этот файл конфигурации использует цикл для создания списка имен, которые являются частью конфигурации Foo_other. Итак, этот язык конфигурации поставляется с очень мощным "препроцессором" с доступной библиотекой времени выполнения. Если вы хотите, скажем, найти сложный журнал или извлечь вещи из zip файла и base64, декодировать их, как часть генерации вашей конфигурации (этот подход не рекомендуется, конечно, для случаев, когда вход может быть от ненадежный источник...)

Пакет читает конфигурацию, используя что-то вроде следующего:

conf_globals = {}  # make a namespace
# Give the config file the classes it needs
conf_globals['FooDef']= mypkgconfig.FooDef  # both of these are based ...
conf_globals['BarDef']= mypkgconfig.BarDef  # ... on .DefBase

fname = "user.conf"
try:
    exec open(fname) in conf_globals
except Exception:
    ...as needed...
# now find all the definitions in there
# (I'm assuming the names they are defined with are
# significant to interpreting the data; so they
# are stored under those keys here).

defs = {}
for nm,val in conf_globals.items():
    if isinstance(val,mypkgconfig.DefBase):
        defs[nm] = val

Итак, наконец, доводя до точки, globals() полезен при использовании такого пакета, если вы хотите тщательно отмерить ряд определений:

for idx in range(20):
    varname = "Foo_%02d" % i
    globals()[varname]= FooDef("one of several", id_code = i+1, scale_ratio = 2**i)

Это эквивалентно написанию

Foo_00 = FooDef("one of several", id_code = 1, scale_ratio=1)
Foo_01 = FooDef("one of several", id_code = 2, scale_ratio=2)
Foo_02 = FooDef("one of several", id_code = 3, scale_ratio=4)
... 17 more ...

Пример пакета, который получает свой ввод путем сбора кучи определений из модуля python, - PLY (Python-lex-yacc) http://www.dabeaz.com/ply/ - в этом случае объекты в основном являются объектами функций, но метаданные из объектов функции (их имена, докстры и порядок определения) также являются частью ввода. Это не такой хороший пример использования globals(). Кроме того, он импортируется с помощью "конфигурации" - последний является обычным питоном script, а не наоборот.

Я использовал "декларативный питон" в нескольких проектах, над которыми работал, и имел возможность использовать globals() при написании конфигураций для них. Вы, конечно же, могли бы утверждать, что это было связано с недостатком способа разработки "языка" конфигурации. Использование globals() таким образом не дает очень четких результатов; просто результаты, которые могут быть легче поддерживать, чем выписывать десятки почти идентичных утверждений.

Вы также можете использовать его для предоставления значения переменных в файле конфигурации в соответствии с их именами:

# All variables above here starting with Foo_k_ are collected
# in Bar_klist
#
foo_k = [ v for k,v in globals().items() if k.startswith('Foo_k_')]
Bar_klist  = BarDef( foo_k , method = "kset")

Этот метод может быть полезен для любого модуля python, который определяет множество таблиц и структур, чтобы упростить добавление элементов в данные, без необходимости поддерживать ссылки.