嵌套函数的名称是什么?为什么 eval 看不到嵌套函数?

what's the name of a nested function ? why doesn't eval see the nested function?

当我尝试 运行 此代码时出现以下错误。我正在尝试用函数指针初始化一个列表。看起来 eval 没有看到函数。我猜我不明白正在发生某种范围界定。如您所见,当我手动创建 table 时它会起作用。我试图避免维护函数列表。当我将函数设为全局时,这也有效。

 Traceback (most recent call last):
   File "/home/westgate/code/python/try/x.py", line 27, in <module>
     main()
   File "/home/westgate/code/python/try/x.py", line 23, in main
     fxns_eval = [eval(fxn_name) for fxn_name in dir() if fxn_name.startswith('fxn_')]
   File "/home/westgate/code/python/try/x.py", line 23, in <listcomp>
     fxns_eval = [eval(fxn_name) for fxn_name in dir() if fxn_name.startswith('fxn_')]
   File "<string>", line 1, in <module>
 NameError: name 'fxn_bar' is not defined

import inspect

def main():

    def fxn_foo():
        print('in foo '+inspect.currentframe().f_code.co_name)

    def fxn_bar():
        print('in bar '+inspect.currentframe().f_code.co_name)

    for i in dir():
        if i.startswith('fxn_'):
            print(i)

    fxn_bar()

    fxns = [ fxn_foo, fxn_bar ]

    fxns[1]()

    fxns_eval = [eval(fxn_name) for fxn_name in dir() if fxn_name.startswith('fxn_')]

    fxns_eval[1]()

main()

问题是您没有明确传递 locals,所以 .来自 docs:

If both dictionaries are omitted, the expression is executed in the environment where eval() is called.

但是,环境是列表理解,它创建了自己的范围,并且这些函数都不在列表理解的本地名称空间中,也不在全局名称空间中。您需要 main 的本地名称空间 所以请注意,这有效:

>>> def main():
...    def foo(): 'foo'
...    print(eval('foo'))
...
>>> main()
<function main.<locals>.foo at 0x10c3ba6a8>

明确传递 globalslocals()但是您必须将它们用作列表理解作用域的自由变量,因为它本质上就像另一个嵌套函数作用域,您也不能只这样做:

>>> def main():
...    def foo(): 'foo'
...    def bar(): 'bar'
...    print([eval(x, globals(), locals()) for x in dir()])
...
>>> main()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in main
  File "<stdin>", line 4, in <listcomp>
  File "<string>", line 1, in <module>
NameError: name 'bar' is not defined

的确,这相当于根本不传递参数

你可以这样做:

>>> def main():
...    def foo(): 'foo'
...    def bar(): 'bar'
...    locs, globs = locals(), globals()
...    print([eval(x, globs, locs) for x in dir()])
...
>>> main()
[<function main.<locals>.bar at 0x10bded1e0>, <function main.<locals>.foo at 0x10c3ba6a8>, {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'n1': 1014.308, 'n0': 961.06, 'p1': 18.59, 'p0': 19.65, 'q1': 1014.308, 'q0': 961.06, 'main': <function main at 0x10c3ba620>}, {'foo': <function main.<locals>.foo at 0x10c3ba6a8>, 'bar': <function main.<locals>.bar at 0x10bded1e0>, 'globs': {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'n1': 1014.308, 'n0': 961.06, 'p1': 18.59, 'p0': 19.65, 'q1': 1014.308, 'q0': 961.06, 'main': <function main at 0x10c3ba620>}, 'locs': {...}}]
>>>