निम्नलिखित एक अजगर कोड ast और symtable संकुल का उपयोग करके स्निपेट है। मैं कोड को पार्स करने और प्रकारों की जांच करने की कोशिश कर रहा हूं। लेकिन वास्तविक चर संदर्भित होने के लिए ऑब्जेक्ट्स को पार करने के तरीके को समझ में नहीं आता है।अजगर ast पैकेज: traversing वस्तु पदानुक्रम
निम्नलिखित कोड एक नोडविजिटर लागू करता है, और एक फ़ंक्शन कंपाइलर को प्रस्तुत किया जाता है और संकलक द्वारा पार्स किया जाता है और अस्थिर चला जाता है। कार्य का विश्लेषण किया जा रहा है (eval_types) कुछ वस्तुओं को पारित किया गया है।
नीचे दिए गए कोड भाग हैं जो उदाहरण बनाते हैं। मैंने प्रत्येक खंड के लिए कुछ टिप्पणियां जोड़ दी हैं। कोड को चलाने के लिए, "भाग" को फिर से इकट्ठा करने की आवश्यकता है।
आयात और एक कार्य को पार्सिंग के लिए कोड के ब्लॉक को अनदेखा करने के लिए।
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)))
निम्नलिखित कुछ सरल वर्ग हैं जिनका उपयोग फ़ंक्शन में किया जाएगा जिसे एएसटी के साथ विश्लेषण और विश्लेषण किया जाएगा।
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 समारोह समारोह है कि एएसटी के साथ विश्लेषण किया जाएगा है।
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']
नोड आगंतुक बनाना बुरा नहीं लगता है, लेकिन मैं बाहर समझ नहीं सकता एक वस्तु पदानुक्रम पार करने के लिए कैसे। सामान्य मामले में परिवर्तनीय एक्सेस किया जा रहा है किसी ऑब्जेक्ट में गहरा दफनाया जा सकता है। अस्थिर आगंतुक से वास्तविक चर को कैसे पहुंचाया जा सकता है? मैं केवल देखता हूं कि ऑब्जेक्ट नोड पर है लेकिन परिणामस्वरूप परिवर्तनीय पहुंच क्या है कोई अतिरिक्त जानकारी नहीं है।
यकीन नहीं है कि मैं जो चाहता हूं उसका पालन करता हूं। क्या आपको ".val" नहीं मिल रहा है? क्या आपने उस नोड के नीचे रिकर्सिंग करने की कोशिश की है? यह लंबे समय से है क्योंकि मैंने इसका इस्तेमाल किया था, लेकिन मुझे याद है कि आपको अपने मामले में, visit_name से visit_children को कॉल करने की आवश्यकता होगी। –
@andrewcooke टिप्पणियों के लिए धन्यवाद! हां, मैं ऑब्जेक्ट्स (z.val, xo.xi.x, xo.xf.x) को पार्स करना जारी रखना चाहता हूं और कथन में उपयोग किए गए वास्तविक चर पर अधिक जानकारी निर्धारित करना चाहता हूं। सरल मामला होगा, z = x + y + xo_xi_x + xo_xf_x, जहां वेरिएबल ऑब्जेक्ट्स में एम्बेडेड (दफन नहीं) होते हैं और वेरिएबल/गुण/प्रकार के चर को उपरोक्त कोड स्निपेट में निर्धारित किया जा सकता है। मैं इन प्रकार के नोड्स पर स्पष्ट रूप से visit_children को कॉल करने के साथ प्रयोग करूंगा। एक बार फिर धन्यवाद। –
एएसटी पैकेज की समझ विकसित करने वाली छोटी (धीमी) प्रगति करना। इस उदाहरण के लिए, ऑब्जेक्ट "विशेषताएँ" ** visit_Attribute ** की यात्रा करेगा। अब मुझे बस यह निर्धारित करने की आवश्यकता है कि ** visit_Name ** में कोई ऑब्जेक्ट है (बच्चे हैं?) तो visit_Attribute में समाप्त करें और पीछे की ओर काम करें (पेड़ का बैक अप लें)। –