gpt4 book ai didi

Python ast 包 : traversing object hierarchies

转载 作者:太空狗 更新时间:2023-10-29 18:12:35 26 4
gpt4 key购买 nike

以下是使用 astsymtable 的 Python 代码片段包。我正在尝试解析代码并检查类型。但是我不明白如何遍历对象以获取实际变量被引用。

下面的代码实现了一个NodeVisitor,一个函数被呈现给编译器,由编译器解析,ast walked。被分析的函数 (eval_types) 被传递了几个对象。

下面是构成示例的代码块。我为每个 block 添加了一些评论。要运行代码,需要重新组装“ block ”。

用于取消缩进代码块以进行解析的导入和函数。

import inspect
import ast
import symtable
from tokenize import generate_tokens, untokenize, INDENT
from cStringIO import StringIO

# _dedent borrowed from the myhdl package (www.myhdl.org)
def _dedent(s):
"""Dedent python code string."""

result = [t[:2] for t in generate_tokens(StringIO(s).readline)]
# set initial indent to 0 if any
if result[0][0] == INDENT:
result[0] = (INDENT, '')
return untokenize(result)

下面是节点访问者,它有通用的未处理和名称访问者重载。

class NodeVisitor(ast.NodeVisitor):
def __init__(self, SymbolTable):
self.symtable = SymbolTable
for child in SymbolTable.get_children():
self.symtable = child
print(child.get_symbols())

def _visit_children(self, node):
"""Determine if the node has children and visit"""
for _, value in ast.iter_fields(node):
if isinstance(value, list):
for item in value:
if isinstance(item, ast.AST):
print(' visit item %s' % (type(item).__name__))
self.visit(item)

elif isinstance(value, ast.AST):
print(' visit value %s' % (type(value).__name__))
self.visit(value)

def generic_visit(self, node):
print(type(node).__name__)
self._visit_children(node)

def visit_Name(self, node):
print(' variable %s type %s' % (node.id,
self.symtable.lookup(node.id)))
print(dir(self.symtable.lookup(node.id)))

以下是一些简单的类,将在将使用 AST 进行解析和分析的函数中使用。

class MyObj(object):
def __init__(self):
self.val = None

class MyObjFloat(object):
def __init__(self):
self.x = 1.

class MyObjInt(object):
def __init__(self):
self.x = 1

class MyObjObj(object):
def __init__(self):
self.xi = MyObjInt()
self.xf = MyObjFloat()

下面是测试函数,eval_types函数是要用AST分析的函数。

def testFunc(x,y,xo,z):

def eval_types():
z.val = x + y + xo.xi.x + xo.xf.x

return eval_types

执行示例、编译函数和分析的代码。

if __name__ == '__main__':
z = MyObj()
print(z.val)
f = testFunc(1, 2, MyObjObj(), z)
f()
print(z.val)
s = inspect.getsource(f)
s = _dedent(s)
print(type(s))
print(s)

SymbolTable = symtable.symtable(s,'string','exec')
tree = ast.parse(s)
v = NodeVisitor(SymbolTable)
v.visit(tree)

以下是直到名字访问为止的示例输出。

Module
visit item FunctionDef
FunctionDef
visit value arguments
arguments
visit item Assign
Assign
visit item Attribute
Attribute
visit value Name
variable z type <symbol 'z'>
['_Symbol__flags', '_Symbol__name', '_Symbol__namespaces',
'_Symbol__scope', '__class__', '__delattr__', '__dict__',
'__doc__', '__format__', '__getattribute__', '__hash__',
'__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '__weakref__', 'get_name', 'get_namespace',
'get_namespaces', 'is_assigned', 'is_declared_global',
'is_free', 'is_global', 'is_imported', 'is_local',
'is_namespace', 'is_parameter', 'is_referenced']

创建节点访问者似乎还不错,但我想不通如何遍历对象层次结构。在一般情况下,变量被访问的对象可能深埋在对象中。如何获取 ast 访问者访问的实际变量?我只看到节点处有一个对象,但没有关于结果变量访问的附加信息。

最佳答案

我不知道你是否还在寻找这个,但看起来你只需要添加一个 visit_Attribute 并向后遍历。如果将此添加到示例中:

def visit_Attribute(self, node):
print(' attribute %s' % node.attr)
self._visit_children(node)

xo.xf.x 的输出是:

Add
visit value Attribute
attribute x
visit value Attribute
attribute xf
visit value Name
variable xo type <symbol 'xo'>
visit value Load

根据您想对此执行的操作,您只需要将属性存储在列表中直到遇到 Name,然后反转它们。

关于Python ast 包 : traversing object hierarchies,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9425409/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com