如何检查具有给定名称的变量是否为非本地变量?

时间:2018-09-25 18:51:42

标签: python python-3.x stackframe python-nonlocal

给出一个堆栈框架和一个变量名,如何判断该变量是否为非本地变量?示例:

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 :(得分:5)

检查框架的代码对象的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中。