Python - Как получить словарь (или даже список) переменных в определенной области; более конкретный, чем местные / глобальные ()

Таким образом, название в значительной степени говорит обо всем.

например, давайте посмотрим на пример кода ниже:

## How can I obtain a dict/list (like locals()) of all the variables in second and/or third layer scopes via a command 
# coming from the first layer?
## Or another example would be how could I obtain the variables "locals() style" from the thirdlayer via a 
# command from the second layer?
# essentially can a parent function/class access a list/dict of a child function
# or class??

def firstLayer():
     a = 4.7
     q = locals()
     print(q)
     # local vars of 1st layer
     def secondlayer():
          b = 7
          r = locals()
          print(r)
          # local vars of 2nd layer
          def thirdlayer():
               c = False
               s = locals()
               i = globals()
               print('c:\n', c, "\nglobals from 3rd layer:\n\t", i)
              # local vars of 3rd layer
          thirdlayer()

     secondlayer()
firstLayer()

sample_var = globals()
print(sample_var)
# returns the list of global variables

Чтобы повторить то, что я сказал в комментариях в коде, по сути, есть ли какой-нибудь способ, которым я могу получить список всех переменных, локальных для "дочерней" области видимости? Я знаю, что функции отключены, но если их невозможно сделать, это их более сложный код, который может достичь этого, и я мог бы интегрировать его в функцию или класс, если это необходимо.

РЕДАКТИРОВАТЬ: уточнять дальше; вот ситуация, в которой я нахожусь.

def varsfunc():
    font1 = "Harlow Solid"
    grey = '#454545'
    font2 = 'Mistral'
    font3 = 'Italic 35px Times New Roman'
    pnk = 'pink'
    grn = 'green'
    return locals()

По сути, я создаю модуль, и пользователь должен создать некоторый тип функции, в которой он перечисляет все переменные, которые он хотел бы объявить для использования для изменения файла CSS. По сути, я бы хотел, чтобы пользователю не приходилось набирать "return locals()". Я хочу добиться этого, заставив конечных пользователей обернуть вышеописанную примерную функцию в декоратор, который будет эквивалентен возвращению locals () именно той области, которую я хочу. Декоратор не работает для меня, потому что он находится во внешней области.

ЧТОБЫ ДАЛЕЕ БОЛЬШЕ ОЧИСТИТЬ: мне нужен декоратор / функция, которая оборачивает другую функцию (т.е. декоратор), которая может получить доступ и создать список дочернего элемента.

def module_decorator_func_thing():
     r = command_that_acts_like_locals()_but_for_child_scopes
     def user_var_list():
          font1 = 'green'
          font2 = 'pink'
     # back in "module_decorator_func_thing"'s scope
     print(r) # this variable should contain only a dict/list containing the
     # the following:
     # r = {'font1': 'green', 'font2': 'pink')

в настоящее время пользователи должны сделать это:

def vars_func_container():
     font1 = 'green'
     font2 = 'pink'
     return locals() #  <---- I want the user to not have to type this and for 
    # a function decorator to take care of it instead possibly.

Информация для @aguy и других желающих получить дополнительную информацию. Словарь / список, который я получаю по советам ваших парней, будет отправлен в эту функцию для выполнения реальной работы программы. (Если бы я начал использовать списки, мне нужно было бы преобразовать их в словарь, но это не проблема для меня.) Диктовка переменных используется с этой функцией для "компиляции / компиляции"(Pun на слове "Python" ' + ' компилируется) и вставляется в параметр "variable". Например, вы выполняете функцию, как это.

compyle("My sample title", return_stylesheet_from_func(*insert .css filename), 
return_variables_from_function(*insert function containing variables*), "**True/False to turn on compilation**", 
"**True/False to turn on annotations/suggestions**")

def compyle(title, style_sheet, variables, boolean=False, boolean2=True):
    """
    :param title: The name you wish your .css file to be named.
    :param style_sheet: The name of the multi-line string that will compose your .css file
    :param variables: The name of the dictionary containing your .pcss variables
    :param boolean: A.K.A the "Compiler Parameter" - Turns the compiler on or off
    :param boolean2: A.K.A the "Annotation Parameter" - Turns annotations on or off
    :return: returns compiled .pcss text as normal .css style text to be utilized with .html
    """
    # -----------------------------------
    file_name = title + ".css"
    replace_num = len(variables.keys())
    counter = replace_num
    content = style_sheet
    # -----------------------------------
    # add theme support with namedtuple's formatted to mimic structs in C/C++
    # this will be a major feature update as well as a nice way to allow the future prospect of integrating C/C++ into
    # the compiler. Info: https://stackru.com/questions/35988/c-like-structures-in-python
    for k, v in variables.items():
        counter -= 1
        content = content.replace(k, v, replace_num)
        if counter == 0:
            break
        else:
            pass
    looped_content = str(content)
    id_content = looped_content.replace("hash_", "#")
    output = id_content.replace("dot_", ".")

    if boolean is True:
        if boolean2 is True:
            output = " /* --- Pyle Sheet --- */\n" + output
            with open(file_name, 'w') as writ:
                writ.write(output)
                writ.close()
                print('compiled successfully; The file was saved as ' + "\"" + file_name + "\".")
        elif boolean2 is False:
            pass
        else:
            logging.warning("An Error Occurred - see module, documentation, or online Q&A for assistance.")
    elif boolean is False:
        if boolean2 is True:
            print('compiled successfully; The file ' + "\"" + file_name + "\"" + "was not saved/created.")
        elif boolean2 is False:
            pass
        else:
            logging.warning("An Error Occurred - see module, documentation, or online Q&A for assistance.")
    else:
        logging.warning('An Error Occurred with the Compile Parameter (See: boolean in pyle_sheets source file) - \ '
                        'see module, documentation, or online Q&A for assistance.')

2 ответа

Решение

Я не вижу никакого способа сделать это, не углубившись довольно глубоко; то, что следует, является самым простым решением, которое я придумала.

как это устроено

Используя модуль ast, мы просматриваем код данной функции и находим все назначения. Они оцениваются в заданном пространстве имен, и это пространство имен возвращается.

код

import ast
import functools
import inspect

def returnAssignments(f):
    @functools.wraps(f)
    def returner():
        assignments = dict()
        for node in ast.walk(ast.parse(inspect.getsource(f))):
            if isinstance(node, ast.Assign):
                exec(compile(ast.Module([node]), '<ast>', 'exec'),
                     globals(),
                     assignments)
        return assignments
    return returner

использование

from ra import returnAssignments

@returnAssignments
def foo():
    this = 'something'
    that = 37
    the_other = object()

print(foo())

выход

rat@pandion:~/tmp$ python test.py
{'this': 'something', 'that': 37, 'the_other': <object object at 0x10205b130>}

Интересно, может ли такое грубое решение, которое я привожу здесь, быть полезным для вас? Обратите внимание, что я не проверял это во всех случаях, так что это может быть немного грубым. Кроме того, он возвращает все в виде строки, поведение, которое вы можете захотеть изменить.

Определите функцию:

def get_local_vars_from_function(f):
    import inspect
    s = inspect.getsourcelines(f)[0]
    d = {}
    for l in s:
        if '=' in l:
            var, val = l.split('=')
            var = var.strip()
            val = val.strip()
            d[var] = val
    return d

Тогда использовать это:

In[91]: get_local_vars_from_function(user_var_list)
Out[91]: {'font1': "'green'", 'font2': "'pink'"}
Другие вопросы по тегам