【问题标题】:Identify variables that are lists of strings in the caller scope识别作为调用者范围内字符串列表的变量
【发布时间】:2018-08-23 13:47:35
【问题描述】:

我想识别用户在其交互式 shell 中定义的所有字符串列表。

def lists_of_strings():
    d = dict(globals(), **locals())
    d = {k:v for (k, v) in d.items() if not k.startswith("_") and k != 'In'}
    res = {}
    for k, v in d.items():
        if isinstance(v, list):
            if all(map(lambda x: isinstance(x, str), v)):
                res[k] = v
    return res

当我在当前的 shell 中定义这个函数时,它可以工作:

>>> lists_of_strings()
{}
>>> mylist = ["a", "b"]
>>> lists_of_strings()
{"mylist": ["a", "b"]}

现在,如果我将这个函数移动到模块 mymodule 中并导入它:

>>> from mymodule import lists_of_strings
>>> lists_of_strings()
{}
>>> mylist = ["a", "b"]
>>> lists_of_strings()
{}

该函数总是返回一个空字典。为什么会这样,更重要的是,我可以解决它吗?

一些上下文:我正在尝试在我的模块中编写一个帮助程序来识别用户在当前 jupyter notebook 中定义的合适变量。我的目标是询问用户是否想将这些变量用作某些预定义函数的参数。

【问题讨论】:

    标签: python module jupyter-notebook ipywidgets


    【解决方案1】:

    Python 的globals 内置函数返回包含当前模块 的全局变量的字典。这是一个非常好的功能,因为“全局”变量不是进程范围的,模块(因此是文件)范围 - 允许每个模块作为命名空间工作。这简化了避免大型系统中名称冲突的大量工作(如果使用第三方组件,则更是如此)。

    但是,是的,有一种方法可以访问另一个正在运行的上下文的全局变量。所有 Python 代码都在 frame 对象的上下文中运行 - 它保留对当前使用的实际字节码、局部变量和全局变量的引用。框架对象的 f_globals 属性实际上与内置 globals 返回的字典相同。

    因此,您所要做的就是获取对发生函数调用的框架对象的引用 - 这可以通过获取当前框架的 .f_back 属性来完成。

    这意味着如果您将函数更改为:

    import sys
    
    def lists_of_strings():
        caller_frame = sys._getframe().f_back
        d = dict(caller_frame.f_globals, **caller_frame.f_locals)
        d = {k:v for (k, v) in d.items() if not k.startswith("_") and k != 'In'}
        res = {}
        for k, v in d.items():
            if isinstance(v, list):
                if all(map(lambda x: isinstance(x, str), v)):
                    res[k] = v
        return res
    

    也就是说,重要的是要注意并非所有代码都需要使用框架。如果您想简单地了解已知模块中的 global 变量,则可以使用该模块的 __dict__ 属性:

    import math
    print (math.__dict__)
    

    【讨论】:

    • 这太棒了!你的解释让我大吃一惊,我不知道 python 有机制来做这种事情。
    猜你喜欢
    • 2013-12-20
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多