如何从ast.FunctionDef节点创建一个函数对象?

时间:2018-02-13 05:10:04

标签: python abstract-syntax-tree

我正在尝试理解执行python代码的过程。假设源具有函数定义。使用<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class='element'>New Class Will Be Added Before 20% Of This Div</div> <div class='element'>New Class Will Be Added Before 20% Of This Div</div> <div class='element'>New Class Will Be Added Before 20% Of This Div</div> <div class='element'>New Class Will Be Added Before 20% Of This Div</div> <div class='element'>New Class Will Be Added Before 20% Of This Div</div>,我将其解析为ast,它将包含ast.parse()节点类的实例。此节点实例不是可调用的,并且与函数对象不同。如何从这个ast创建函数对象及其所有dunder属性?

2 个答案:

答案 0 :(得分:4)

你不能(据我所知)编译一个像FunctionDef一样的任意单个AST节点。你可以做的是将整个代码片段编译为模块,在提供的命名空间中执行,然后访问其内容,包括函数。这是一个例子:

import ast

txt = """
def foo(x, y=2):
    z = x*y + 3
    print("z is", z)
    return z**2
"""

tree = ast.parse(txt, mode='exec')
code = compile(tree, filename='blah', mode='exec')
namespace = {}
exec(code, namespace)

现在namespace相当于包含给定代码的模块的__dict__。您可以访问并调用该函数:

>>> namespace['foo']
<function foo at 0x00000000023A2B70>
>>> namespace['foo'](2, 3)
z is 9
81

请注意,如果您只想做这件事,则根本不需要使用ast。您可以直接使用compile(tree, filename='blah', mode='exec')编译源字符串。事实上,甚至不需要涉及compile,因为您可以直接使用exec(txt, namespace)执行源字符串。如果您的目标只是将最终的函数对象取出,那么您根本不需要访问内部解析和编译步骤;只需在命名空间中执行整个操作,然后从那里获取函数。

答案 1 :(得分:0)

如果函数在类下,则下面的代码会有所帮助- 导入ast

txt = """
class MyClass():
  def foo(x, y=2):
      z = x*y + 3
      print("z is", z)
      return z**2
"""

tree = ast.parse(txt, mode='exec')
code = compile(tree, filename='blah', mode='exec')
namespace = {}
exec(code, namespace)
val = "foo"
dict_item = namespace["MyClass"].__dict__.items()
for x,y in list(dict_item):
  if val == x:
    print(x)
    print(y)
    print(type(x))
    print(type(y))