识别lambda表达式中的全局符号

时间:2016-09-08 18:17:16

标签: python lambda

我需要获取所有符号的名称列表,以便评估或执行一段代码。我试图使用symtable模块,但似乎它没有正确处理lambdas和内部函数(def s在其他代码中)。考虑一下:

import symtable
symtable.symtable("x+y", '<string>', 'exec').get_symbols()

我明白了:[<symbol 'y'>, <symbol 'x'>]这正是我所期待的。

但是当我写这篇文章时:

symtable.symtable("z=lambda x: x+y; z(10)", '<string>', 'exec').get_symbols()

结果是:[<symbol 'z'>]我没有关于x(没关系,它是一个局部变量)的信息,也没有y(这是全局的,这就是我需要的)

但是,当我尝试使用exec("z=lambda x: x+y; z(10)")对此进行评估时,y的值丢失了。有没有办法可以识别必须提供给表达式或代码的所有符号的名称,以便可以对其进行评估/执行?

1 个答案:

答案 0 :(得分:0)

没有多少...我需要查看子符号表。递归是首选工具:

import symtable

def find_global_symbols(table):
    symbols = set()
    for t in table.get_children():
        symbols |= find_global_symbols(t)
    symbols |= set(s.get_name() for s in table.get_symbols() if s.is_global())
    return symbols

table = symtable.symtable("z=lambda x: x+y; z(10)", '<string>', 'exec')
global_symbols = find_global_symbols(table)

这给了我y作为答案。这就是我需要的。现在我知道我必须提供y的值才能执行相关代码。

更新:如果我考虑在每个范围内导入的名称,实际上可能会有改进

def find_global_symbols(table, imports):
    imports = imports | set(s.get_name() for s in table.get_symbols() if s.is_imported())
    symbols = set()
    for s in table.get_symbols():
        if s.is_global() and s.get_name() not in imports:
            symbols.add(s.get_name())
    for t in table.get_children():
        symbols |= find_global_symbols(t, imports)
    return symbols

table = symtable.symtable("z=lambda x: x+y; z(10)", '<string>', 'exec')
global_symbols = find_global_symbols(table, set())