Получить изложение всех переменных, находящихся в настоящее время в области видимости, и их значений - PullRequest
32 голосов
/ 25 июня 2009

Рассмотрим этот фрагмент:

globalVar = 25

def myfunc(paramVar):
    localVar = 30
    print "Vars: {globalVar}, {paramVar}, {localVar}!".format(**VARS_IN_SCOPE)

myfunc(123)

Где VARS_IN_SCOPE - это диктовка, которую я после этого должен содержать globalVar, paramVar и localVar, среди прочего.

Я бы хотел иметь возможность ссылаться на все переменные, которые в данный момент находятся в области видимости внутри строки. Следовательно, ожидаемый результат будет:

Vars: 25, 123, 30

Я могу добиться этого, передав **dict(globals().items() + locals().items()) на format(). Всегда ли это правильно или есть некоторые угловые случаи, когда это выражение будет обрабатываться неправильно?

Переписано для уточнения вопроса.

Ответы [ 5 ]

34 голосов
/ 25 июня 2009

Лучший способ объединить два дикта, как вы делаете (с переопределением глобалов на локальном уровне), это dict(globals(), **locals()).

Чего не хватает в подходе объединения глобальных и локальных объектов: (а) встроенные функции (я думаю, это преднамеренно, т. Е. Вы не думаете о встроенных функциях как «переменных» ... но они МОГУТ быть, если вы так решите!) -) и (b) если вы находитесь в вложенной функции, любые переменные, которые являются локальными для включающих функций (нет действительно хорошего способа получить контроль со всеми этими , плюс - только те, которые явно доступны во вложенной функции, т. е. ее «свободные переменные», в любом случае выживают как ячейки в замыкании.

Я полагаю, что эти проблемы не имеют большого значения для вашего предполагаемого использования, но вы упомянули "угловые случаи" ;-). Если вам нужно охватить их, есть способы получить встроенные (это легко) и (не так просто) все ячейки (переменные из вложенных функций, которые вы явно упомянули во вложенной функции - thefunction.func_code.co_freevars, чтобы получить имена, thefunction.func_closure для получения ячеек, cell_contents для каждой ячейки, чтобы получить ее значение). (Но помните, что это будут только переменные из включающих функций, к которым явно обращен в коде вашей вложенной функции!).

8 голосов
/ 25 июня 2009

Это делает то, что вы хотели?

d = dict(globals())
d.update(locals())

Если я правильно прочитал документацию, вы создаете копию диктата globals(), затем вы перезаписываете любые дубликаты и и вставляете новые записи из диктата locals() (поскольку locals() в любом случае предпочтение в пределах вашей сферы действия.)


Мне не повезло в получении правильной функции для возврата полного словаря переменных в области действия , вызывающей функцию. Вот код (я использовал pprint только для правильного форматирования вывода для SO):

from pprint import *

def allvars_bad():
    fake_temp_var = 1
    d = dict(globals())
    d.update(locals())
    return d

def foo_bad():
    x = 5
    return allvars_bad()

def foo_good():
    x = 5
    fake_temp_var = "good"
    d = dict(globals())
    d.update(locals())
    return d

pprint (foo_bad(), width=50)
pprint (foo_good(), width=50)

и вывод:

 {'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d316ec>,
 '__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'temp.py',
 '__name__': '__main__',
 '__package__': None,
 'allvars_bad': <function allvars_bad at 0xb7d32b1c>,
 'd': <Recursion on dict with id=3084093748>,
 'fake_temp_var': 1,
 'foo_bad': <function foo_bad at 0xb7d329cc>,
 'foo_good': <function foo_good at 0xb7d32f0c>,
 'isreadable': <function isreadable at 0xb7d32c34>,
 'isrecursive': <function isrecursive at 0xb7d32c6c>,
 'pformat': <function pformat at 0xb7d32bc4>,
 'pprint': <function pprint at 0xb7d32b8c>,
 'saferepr': <function saferepr at 0xb7d32bfc>}
{'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d316ec>,
 '__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'temp.py',
 '__name__': '__main__',
 '__package__': None,
 'allvars_bad': <function allvars_bad at 0xb7d32b1c>,
 'd': <Recursion on dict with id=3084093884>,
 'fake_temp_var': 'good',
 'foo_bad': <function foo_bad at 0xb7d329cc>,
 'foo_good': <function foo_good at 0xb7d32f0c>,
 'isreadable': <function isreadable at 0xb7d32c34>,
 'isrecursive': <function isrecursive at 0xb7d32c6c>,
 'pformat': <function pformat at 0xb7d32bc4>,
 'pprint': <function pprint at 0xb7d32b8c>,
 'saferepr': <function saferepr at 0xb7d32bfc>,
 'x': 5}

Обратите внимание, что во втором выводе мы перезаписали fake_temp_var, и x присутствует; первый вывод включал только локальные переменные в пределах allvars_bad.

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

<Ч />

Я подозревал, что есть какой-то объект в виде рамки, я просто (не знаю, где) искать его.

Это работает для вашей спецификации, я считаю:

def allvars_good(offset=0):
    frame = sys._getframe(1+offset)
    d = frame.f_globals
    d.update(frame.f_locals)
    return d


def foo_good2():
    a = 1
    b = 2
    return allvars_good()

->

{'PrettyPrinter': <class pprint.PrettyPrinter at 0xb7d6474c>,
 '__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__file__': 'temp.py',
 '__name__': '__main__',
 '__package__': None,
 'a': 1,
 'allvars_bad': <function allvars_bad at 0xb7d65b54>,
 'allvars_good': <function allvars_good at 0xb7d65a04>,
 'b': 2,
 'foo_bad': <function foo_bad at 0xb7d65f44>,
 'foo_good': <function foo_good at 0xb7d65f7c>,
 'foo_good2': <function foo_good2 at 0xb7d65fb4>,
 'isreadable': <function isreadable at 0xb7d65c6c>,
 'isrecursive': <function isrecursive at 0xb7d65ca4>,
 'pformat': <function pformat at 0xb7d65bfc>,
 'pprint': <function pprint at 0xb7d65bc4>,
 'saferepr': <function saferepr at 0xb7d65c34>,
 'sys': <module 'sys' (built-in)>}
2 голосов
/ 25 июня 2009
globalVar = 25

def myfunc(paramVar):
    localVar = 30
    all_vars = locals.copy()
    all_vars.update(globals())
    print "Vars: {globalVar}, {paramVar}, {localVar}!".format(all_vars)

myfunc(123)
2 голосов
/ 25 июня 2009

Вы можете сделать свой собственный:

allvars = dict()
allvars.update(globals())
allvars.update(locals())

или объединить первые две строки:

allvars = dict(globals())
allvars.update(locals())
1 голос
/ 25 июня 2009

Интерполяция в строки работает самым простым способом. Просто перечислите свои переменные. Python проверяет локальных и глобальных для вас.

globalVar = 25

def myfunc(paramVar):
    localVar = 30
    print "Vars: %d, %d, %d!" % ( globalVar, paramVar, localVar )

myfunc(123)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...