Как проверить, является ли переменная с заданным именем нелокальной? - PullRequest
0 голосов
/ 25 сентября 2018

Учитывая кадр стека и имя переменной, как мне узнать, является ли эта переменная нелокальной?Пример:

import inspect

def is_nonlocal(frame, varname):
    # How do I implement this?
    return varname not in frame.f_locals  # This does NOT work

def f():
    x = 1
    def g():
        nonlocal x
        x += 1
        assert is_nonlocal(inspect.currentframe(), 'x')
    g()
    assert not is_nonlocal(inspect.currentframe(), 'x')

f()

1 Ответ

0 голосов
/ 25 сентября 2018

Проверьте код объекта фрейма co_freevars, который является кортежем имен переменных замыкания, которые использует объект кода:

def is_nonlocal(frame, varname):
    return varname in frame.f_code.co_freevars

Обратите внимание, что это переменные замыкания, тип переменных, которыеnonlocal заявление ищет.Если вы хотите включить все переменные, которые не являются локальными, вы должны проверить co_varnames (локальные переменные не используются во внутренних областях) и co_cellvars (локальные переменные, используемые во внутренних областях):

def isnt_local(frame, varname):
    return varname not in (frame.f_code.co_varnames + frame.f_code.co_cellvars)

Кроме того, не путайте вещи с co_names, который в настоящее время неверно документирован.В inspect документах сказано, что co_names для локальных переменных, но co_names является своего рода корзиной «всего остального».Он включает в себя глобальные имена, имена атрибутов и несколько видов имен, участвующих в импорте - в основном, если ожидается, что для выполнения действительно потребуется строковая форма имени, он указывается в co_names.

...