代码之家  ›  专栏  ›  技术社区  ›  k_ssb

函数链生成nameferror的Python exec

  •  3
  • k_ssb  · 技术社区  · 4 年前

    考虑下面的脚本,它使用 exec 要定义两个函数,其中一个函数调用另一个函数:

    def run_code():
      code = """
    def foo():
      print('foo')
      return 1
    
    def bar():
      print('bar calls foo')
      return 1 + foo()
    
    result = bar()
    """
    
      exec(code, globals(), locals())
      print('Result: {}'.format(locals()['result']))
    
    run_code()
    

    我希望看到以下输出:

    bar calls foo
    foo
    Result: 2
    

    bar calls foo
    Traceback (most recent call last):
      File "minimal.py", line 17, in <module>
        run_code()
      File "minimal.py", line 14, in run_code
        exec(code, globals(), locals())
      File "<string>", line 10, in <module>
      File "<string>", line 8, in bar
    NameError: name 'foo' is not defined
    

    有趣的是,如果 run_code globals() locals() 有了一本新的空字典,它又破了。我也知道 def foo bar 他的身体会让它工作的。

    执行官

    2 回复  |  直到 4 年前
        1
  •  3
  •   juanpa.arrivillaga    4 年前

    documentation :

    如果提供,局部变量可以是任何映射对象。记得在模块上吗 level、globals和locals是同一个字典。如果执行官有两个 如果它嵌入到类定义中。

    和类定义 self . 所以 只是 通过 globals() 字典。或者将同一个dict中的两个传递给两个参数。

    In [4]: def run_code():
       ...:     code = """
       ...: def foo():
       ...:   print('foo')
       ...:   return 1
       ...:
       ...: def bar():
       ...:   print('bar calls foo')
       ...:   return 1 + foo()
       ...:
       ...: result = bar()
       ...: """
       ...:     namespace = {}
       ...:     exec(code, namespace)
       ...:     print('Result: {}'.format(namespace['result']))
       ...:
    
    In [5]: run_code()
    bar calls foo
    foo
    Result: 2
    
        2
  •  0
  •   Aaj Kaal    4 年前
    code = """  
    def foo():
      print('foo')
      return 1
    
    def bar():
      global foo;
      print('bar calls foo')
      return 1 + foo()
    
    result = bar()
    """
    def run_code():
        exec(code, globals(), locals())
        print('Result: {}'.format(locals()['result']))
    
    
    run_code()
    

    bar calls foo
    foo
    Result: 2