简体   繁体   English

识别变量是调用方作用域中的字符串列表

[英]Identify variables that are lists of strings in the caller scope

I would like to identify all the lists of strings that the user has defined in their interactive shell. 我想识别用户在其交互式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

When I define this function in my current shell, it works: 当我在当前shell中定义此函数时,它可以工作:

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

Now if I move this function in a module mymodule and import it: 现在,如果我在模块mymodule移动此函数并将其导入:

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

The function always returns an empty dictionary. 该函数始终返回一个空字典。 Why is that, and more importantly, can I fix it ? 为什么会这样, 更重要的是,我可以修复它吗?

Some context: I am trying to write a helper in my module to identify suitable variables defined by the user in the current jupyter notebook. 一些上下文:我正在尝试在模块中编写一个帮助程序,以识别用户在当前jupyter笔记本中定义的合适变量。 My goal would be to ask the user if they want to use those variables as an argument of some pre-defined function. 我的目标是询问用户是否要将这些变量用作某些预定义函数的参数。

Python's globals built-in returns the dictionary containing the global variables for the current module . 内置的Python globals返回包含当前模块的全局变量的字典。 That is a quite nice feature, since "global" variables are not process-wide, and module (and therefore file) wide - allows each module to work as a namespace. 这是一个非常不错的功能,因为“全局”变量不在进程范围内,并且在模块(因此在文件)范围内-允许每个模块用作名称空间。 That simplifies a lot of work to avoid name clashes in big systems (doubly so if one uses third-party components). 这就避免了在大型系统中避免名称冲突的大量工作(如果使用第三方组件,则避免了这一点)。

But, yes, there is a way to get by to the global variables of another running context. 但是,是的,有一种方法可以获取另一个运行上下文的全局变量。 All Python code is run in context of a frame object - it keeps a reference to the actual bytecode, the local variables, and global variables currently in use. 所有Python代码均在frame对象的上下文中运行-保留对当前使用的实际字节码,局部变量和全局变量的引用。 The f_globals attribute of a frame object is actually the same dictionary that is returned by the globals built-in. 框架对象的f_globals属性实际上与内置的globals返回的字典相同。

So, all you have to do is get a reference to the frame object where the call to your function took place - and this can be done by taking the .f_back attribute of the current frame. 因此,您要做的就是获取对调用函数的框架对象的引用-这可以通过采用当前框架的.f_back属性来完成。

That means your function will work across modules (and upon being imported) if you change it to: 这意味着,如果您将函数更改为以下内容,则它将跨模块工作(并且在导入时):

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

That said, it is important to note that not all code needs to make use of frames. 就是说,需要注意的是,并非所有代码都需要使用框架。 If you want to simply know the global variables in a known module, you can just make use of that module's __dict__ attribute: 如果您只想知道已知模块中的全局变量,则可以使用该模块的__dict__属性:

import math
print (math.__dict__)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM