如何从 ast.FunctionDef 节点创建函数对象?
How to create a function object from an ast.FunctionDef node?
我正在尝试了解执行 python 代码的过程。假设源有一个函数定义。使用 ast.parse()
,我将其解析为一个 ast,它将包含 FunctionDef
节点 class 的一个实例。此节点实例不可调用,与函数对象不同。如何从这个 ast 创建具有所有 dunder 属性的函数对象?
您不能(据我所知)像 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)
执行源字符串。如果你的目标只是得到最终的函数对象,你真的不需要访问内部解析和编译步骤;只需在命名空间中执行整个过程,然后从那里获取函数。
如果函数在 class 下,下面的代码会有所帮助 -
导入 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))
我正在尝试了解执行 python 代码的过程。假设源有一个函数定义。使用 ast.parse()
,我将其解析为一个 ast,它将包含 FunctionDef
节点 class 的一个实例。此节点实例不可调用,与函数对象不同。如何从这个 ast 创建具有所有 dunder 属性的函数对象?
您不能(据我所知)像 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)
执行源字符串。如果你的目标只是得到最终的函数对象,你真的不需要访问内部解析和编译步骤;只需在命名空间中执行整个过程,然后从那里获取函数。
如果函数在 class 下,下面的代码会有所帮助 - 导入 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))