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

Posted

技术标签:

【中文标题】如何检查具有给定名称的变量是不是是非本地的?【英文标题】:How to check if a variable with a given name is nonlocal?如何检查具有给定名称的变量是否是非本地的? 【发布时间】:2019-03-01 11:30:01 【问题描述】:

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

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

【问题讨论】:

如果是本地,varname应该在frame.f_locals吗? @WillemVanOnsem:我有一个错字,我在一两分钟内修正了它。 相关/重复? ***.com/questions/22438219/… @Jean-FrançoisFabre:相关,但不是重复的。但是,那里的答案似乎非常,非常错误! f_back 给出调用者的框架(动态范围),而不是定义者的框架(词法范围)!!! 请注意我没有关闭问题:) 【参考方案1】:

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

【讨论】:

哦,呃!谢谢!!

以上是关于如何检查具有给定名称的变量是不是是非本地的?的主要内容,如果未能解决你的问题,请参考以下文章

检查给定变量是不是为 NaN 的最佳方法是啥? [复制]

检查变量是不是在python中定义的简单方法? [复制]

Delphi 类变量是不是具有全局或线程本地存储?

检查环境变量是不是存在并设置为 True [关闭]

如何检查设备是不是具有给定的功能? [复制]

如何同步ExCeL与PS变量