2

给定一个堆栈帧和一个变量名,我如何判断该变量是否是非本地的?例子:

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()
4

1 回答 1

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.

于 2018-09-25T19:00:11.163 回答