पायथनच्या एएसटी मॉड्यूलद्वारे ॲब्स्ट्रॅक्ट सिंटॅक्स ट्रीमध्ये फेरफार (manipulation) करण्याची क्षमता शोधा. पायथन कोडचे विश्लेषण, बदल आणि प्रोग्रामॅटिकली निर्मिती (generation) करा.
पायथन एएसटी मॉड्यूल: ॲब्स्ट्रॅक्ट सिंटॅक्स ट्री मॅनिपुलेशन सोपे
पायथन ast
मॉड्यूल पायथन कोडच्या ॲब्स्ट्रॅक्ट सिंटॅक्स ट्री (AST) सोबत संवाद साधण्याचा एक शक्तिशाली मार्ग प्रदान करते. एएसटी हे सोर्स कोडच्या सिंटॅक्टिक स्ट्रक्चरचे ट्री रिप्रेझेंटेशन (tree representation) आहे, ज्यामुळे प्रोग्रामॅटिकली (programmatically) पायथन कोडचे विश्लेषण, बदल आणि निर्मिती करणे शक्य होते. हे कोड विश्लेषण साधने, स्वयंचलित रीफॅक्टरिंग (refactoring), स्टॅटिक विश्लेषण (static analysis), आणि अगदी कस्टम भाषा विस्तारांसारख्या (custom language extensions) विविध ऍप्लिकेशन्ससाठी (applications) एक नवीन संधी निर्माण करते. हा लेख तुम्हाला ast
मॉड्यूलच्या मूलभूत गोष्टी, व्यावहारिक उदाहरणे आणि त्याच्या क्षमतांची माहिती देईल.
ॲब्स्ट्रॅक्ट सिंटॅक्स ट्री (AST) म्हणजे काय?
ast
मॉड्यूलमध्ये जाण्यापूर्वी, ॲब्स्ट्रॅक्ट सिंटॅक्स ट्री म्हणजे काय हे समजून घेऊया. जेव्हा पायथन इंटरप्रिटर तुमचा कोड एक्झिक्युट (execute) करतो, तेव्हा पहिले पाऊल म्हणजे कोडला एएसटीमध्ये पार्स करणे. हे ट्री स्ट्रक्चर कोडचे सिंटॅक्टिक घटक जसे की फंक्शन्स, क्लासेस, लूप्स, एक्स्प्रेशन्स (expressions), आणि ऑपरेटर (operators) तसेच त्यांचे संबंध दर्शवते. एएसटी व्हाईटस्पेस (whitespace) आणि कमेंट्ससारखे (comments) अनावश्यक तपशील वगळते, आवश्यक स्ट्रक्चरल माहितीवर लक्ष केंद्रित करते. अशा प्रकारे कोडचे प्रतिनिधित्व करून, प्रोग्राम्ससाठी कोडचे विश्लेषण करणे आणि त्यात फेरफार करणे शक्य होते, जे बर्याच परिस्थितीत अत्यंत उपयुक्त आहे.
ast
मॉड्यूलसह सुरुवात करणे
ast
मॉड्यूल पायथनच्या स्टँडर्ड लायब्ररीचा (standard library) भाग आहे, त्यामुळे तुम्हाला कोणतीही अतिरिक्त पॅकेजेस (packages) इन्स्टॉल (install) करण्याची आवश्यकता नाही. ते वापरणे सुरू करण्यासाठी फक्त इंपोर्ट (import) करा:
import ast
ast
मॉड्यूलचे मुख्य कार्य म्हणजे ast.parse()
, जे पायथन कोडची स्ट्रिंग इनपुट म्हणून घेते आणि एएसटी ऑब्जेक्ट (AST object) परत करते.
code = """
def add(x, y):
return x + y
"""
ast_tree = ast.parse(code)
print(ast_tree)
हे खालीलप्रमाणे आउटपुट (output) करेल: <_ast.Module object at 0x...>
. हे आउटपुट विशेष माहितीपूर्ण नसले तरी, ते दर्शवते की कोड यशस्वीरित्या एएसटीमध्ये पार्स (parsed) झाला आहे. ast_tree
ऑब्जेक्टमध्ये आता पार्स केलेल्या कोडची संपूर्ण रचना आहे.
एएसटी (AST) एक्सप्लोर करणे
एएसटीची रचना समजून घेण्यासाठी, आपण ast.dump()
फंक्शन वापरू शकतो. हे फंक्शन रिकर्सिव्हली (recursively) ट्रीवर फिरते (traverses) आणि प्रत्येक नोडचे (node) विस्तृत प्रतिनिधित्व (detailed representation) प्रिंट करते.
code = """
def add(x, y):
return x + y
"""
ast_tree = ast.parse(code)
print(ast.dump(ast_tree, indent=4))
आउटपुट खालीलप्रमाणे असेल:
Module(
body=[
FunctionDef(
name='add',
args=arguments(
posonlyargs=[],
args=[
arg(arg='x', annotation=None, type_comment=None),
arg(arg='y', annotation=None, type_comment=None)
],
kwonlyargs=[],
kw_defaults=[],
defaults=[]
),
body=[
Return(
value=BinOp(
left=Name(id='x', ctx=Load()),
op=Add(),
right=Name(id='y', ctx=Load())
)
)
],
decorator_list=[],
returns=None,
type_comment=None
)
],
type_ignores=[]
)
हे आउटपुट कोडची श्रेणीबद्ध (hierarchical) रचना दर्शवते. चला त्याचे विश्लेषण करूया:
Module
: संपूर्ण मॉड्यूलचे प्रतिनिधित्व (representing) करणारे रूट नोड.body
: मॉड्यूलमधील विधानांची (statements) सूची.FunctionDef
: फंक्शन (function) व्याख्या (definition) दर्शवते. त्याची विशेषता (attributes) खालीलप्रमाणे आहेत:name
: फंक्शनचे नाव ('add').args
: फंक्शनचे (function) युक्तिवाद (arguments).arguments
: फंक्शनच्या युक्तिवादांबद्दल माहिती आहे.arg
: एक युक्तिवाद दर्शवतो (उदा., 'x', 'y').body
: फंक्शनची बॉडी (statements ची लिस्ट).Return
: रिटर्न स्टेटमेंट दर्शवते.value
: परत (returning) केले जाणारे मूल्य (value).BinOp
: बायनरी ऑपरेशन (binary operation) दर्शवते (उदा., x + y).left
: डावा ऑपरंड (operand) (उदा., 'x').op
: ऑपरेटर (operator) (उदा., 'Add').right
: उजवा ऑपरंड (उदा., 'y').
एएसटी (AST) ट्रॅव्हर्स (Traversing) करणे
ast
मॉड्यूल एएसटी ट्रॅव्हर्स करण्यासाठी ast.NodeVisitor
क्लास (class) पुरवतो. ast.NodeVisitor
चा उपवर्ग (subclass) तयार करून आणि त्याचे मेथड ओव्हरराइड (override) करून, आपण ट्रॅव्हर्स दरम्यान (during the traversal) विशिष्ट नोड प्रकारांवर प्रक्रिया (process) करू शकता. हे कोडची रचना (code structure) तपासण्यासाठी, विशिष्ट नमुने (patterns) ओळखण्यासाठी किंवा माहिती काढण्यासाठी उपयुक्त आहे.
import ast
class FunctionNameExtractor(ast.NodeVisitor):
def __init__(self):
self.function_names = []
def visit_FunctionDef(self, node):
self.function_names.append(node.name)
code = """
def add(x, y):
return x + y
def subtract(x, y):
return x - y
"""
ast_tree = ast.parse(code)
extractor = FunctionNameExtractor()
extractor.visit(ast_tree)
print(extractor.function_names) # Output: ['add', 'subtract']
या उदाहरणामध्ये, FunctionNameExtractor
ast.NodeVisitor
कडून इनहेरिट (inherit) करतो आणि visit_FunctionDef
मेथड ओव्हरराइड करतो. ही मेथड एएसटीमधील (AST) प्रत्येक फंक्शन डेफिनिशन (definition) नोडसाठी (node) कॉल केली जाते. मेथड फंक्शनचे नाव function_names
लिस्टमध्ये (list) जोडते. visit()
मेथड एएसटीच्या ट्रॅव्हर्सची सुरुवात करते.
उदाहरण: सर्व व्हेरिएबल असाइनमेंट (variable assignments) शोधणे
import ast
class VariableAssignmentFinder(ast.NodeVisitor):
def __init__(self):
self.assignments = []
def visit_Assign(self, node):
for target in node.targets:
if isinstance(target, ast.Name):
self.assignments.append(target.id)
code = """
x = 10
y = x + 5
message = "hello"
"""
ast_tree = ast.parse(code)
finder = VariableAssignmentFinder()
finder.visit(ast_tree)
print(finder.assignments) # Output: ['x', 'y', 'message']
हे उदाहरण कोडमधील सर्व व्हेरिएबल असाइनमेंट शोधते. visit_Assign
मेथड प्रत्येक असाइनमेंट स्टेटमेंटसाठी (statement) कॉल केली जाते. ती असाइनमेंटच्या टार्गेटमध्ये (target) पुनरावृत्ती करते आणि, जर टार्गेट एक साधे नाव (ast.Name
) असेल, तर ते नाव assignments
लिस्टमध्ये जोडते.
एएसटीमध्ये बदल करणे
ast
मॉड्यूल तुम्हाला एएसटीमध्ये बदल (modify) करण्याची परवानगी देखील देते. तुम्ही विद्यमान नोडमध्ये (existing nodes) बदल करू शकता, नवीन नोड जोडू शकता किंवा नोड पूर्णपणे काढू शकता. एएसटीमध्ये बदल करण्यासाठी, तुम्ही ast.NodeTransformer
क्लास वापरा. ast.NodeVisitor
प्रमाणेच, तुम्ही ast.NodeTransformer
चा उपवर्ग तयार करता आणि विशिष्ट नोड प्रकार बदलण्यासाठी त्याच्या मेथड ओव्हरराइड करता. मुख्य फरक असा आहे की ast.NodeTransformer
मेथडने (method) सुधारित नोड (modified node) (किंवा त्याऐवजी नवीन नोड) परत करणे आवश्यक आहे. जर मेथड None
परत करत असेल, तर नोड एएसटीमधून काढून टाकला जातो.
एएसटीमध्ये बदल केल्यानंतर, तुम्हाला compile()
फंक्शन वापरून ते एक्झिक्युटेबल (executable) पायथन कोडमध्ये परत कंपाइल (compile) करणे आवश्यक आहे.
import ast
class AddOneTransformer(ast.NodeTransformer):
def visit_Num(self, node):
return ast.Num(n=node.n + 1)
code = """
x = 10
y = 20
"""
ast_tree = ast.parse(code)
transformer = AddOneTransformer()
new_ast_tree = transformer.visit(ast_tree)
new_code = compile(new_ast_tree, '<string>', 'exec')
# Execute the modified code
exec(new_code)
print(x) # Output: 11
print(y) # Output: 21
या उदाहरणामध्ये, AddOneTransformer
ast.NodeTransformer
कडून इनहेरिट करतो आणि visit_Num
मेथड ओव्हरराइड करतो. ही मेथड प्रत्येक संख्यात्मक अक्षरशः नोडसाठी (numeric literal node) (ast.Num
) कॉल केली जाते. मेथड 1 ने वाढवलेल्या मूल्यासह (value) एक नवीन ast.Num
नोड तयार करते. visit()
मेथड सुधारित एएसटी परत करते.
compile()
फंक्शन सुधारित एएसटी, एक फाइलचे नाव (या प्रकरणात <string>
, जे दर्शवते की कोड स्ट्रिंगमधून येतो) आणि एक्झिक्यूशन मोड (execution mode) (कोडच्या ब्लॉकच्या एक्झिक्यूशनसाठी 'exec'
) घेते. ते एक कोड ऑब्जेक्ट (code object) परत करते जे exec()
फंक्शन वापरून एक्झिक्युट केले जाऊ शकते.
उदाहरण: व्हेरिएबलचे नाव बदलणे
import ast
class VariableNameReplacer(ast.NodeTransformer):
def __init__(self, old_name, new_name):
self.old_name = old_name
self.new_name = new_name
def visit_Name(self, node):
if node.id == self.old_name:
return ast.Name(id=self.new_name, ctx=node.ctx)
return node
code = """
def multiply_by_two(number):
return number * 2
result = multiply_by_two(5)
print(result)
"""
ast_tree = ast.parse(code)
replacer = VariableNameReplacer('number', 'num')
new_ast_tree = replacer.visit(ast_tree)
new_code = compile(new_ast_tree, '<string>', 'exec')
# Execute the modified code
exec(new_code)
हे उदाहरण व्हेरिएबलचे नाव 'number'
च्या सर्व घटना 'num'
ने बदलते. VariableNameReplacer
जुने आणि नवीन नाव युक्तिवाद म्हणून घेते. visit_Name
मेथड प्रत्येक नाव नोडसाठी (node) कॉल केली जाते. जर नोडचा आयडेंटिफायर (identifier) जुन्या नावाशी जुळत असेल, तर ते नवीन नावाचे (name) नवीन ast.Name
नोड तयार करते आणि समान संदर्भ (node.ctx
) ठेवते. संदर्भ दर्शवतो की नाव कसे वापरले जात आहे (उदा., लोडिंग, स्टोअरिंग).
एएसटीमधून (AST) कोड तयार करणे
compile()
तुम्हाला एएसटीमधून कोड एक्झिक्युट (execute) करण्याची परवानगी देत असताना, ते कोडला स्ट्रिंग म्हणून मिळवण्याचा मार्ग देत नाही. एएसटीमधून पायथन कोड तयार करण्यासाठी, तुम्ही astunparse
लायब्ररी वापरू शकता. हे लायब्ररी स्टँडर्ड लायब्ररीचा भाग नाही, त्यामुळे तुम्हाला ते प्रथम इन्स्टॉल (install) करणे आवश्यक आहे:
pip install astunparse
नंतर, तुम्ही एएसटीमधून कोड तयार करण्यासाठी astunparse.unparse()
फंक्शन वापरू शकता.
import ast
import astunparse
code = """
def add(x, y):
return x + y
"""
ast_tree = ast.parse(code)
generated_code = astunparse.unparse(ast_tree)
print(generated_code)
आउटपुट खालीलप्रमाणे असेल:
def add(x, y):
return (x + y)
टीप: (x + y)
च्या आसपासचे कंस (parentheses) astunparse
द्वारे योग्य ऑपरेटर प्राधान्य (operator precedence) सुनिश्चित करण्यासाठी जोडले जातात. हे कंस (parentheses) आवश्यक नसले तरी, ते कोडची अचूकता (correctness) सुनिश्चित करतात.
उदाहरण: एक साधे क्लास (class) तयार करणे
import ast
import astunparse
class_name = 'MyClass'
method_name = 'my_method'
# Create the class definition node
class_def = ast.ClassDef(
name=class_name,
bases=[],
keywords=[],
body=[
ast.FunctionDef(
name=method_name,
args=ast.arguments(
posonlyargs=[],
args=[],
kwonlyargs=[],
kw_defaults=[],
defaults=[]
),
body=[
ast.Pass()
],
decorator_list=[],
returns=None,
type_comment=None
)
],
decorator_list=[]
)
# Create the module node containing the class definition
module = ast.Module(body=[class_def], type_ignores=[])
# Generate the code
code = astunparse.unparse(module)
print(code)
हे उदाहरण खालील पायथन कोड तयार करते:
class MyClass:
def my_method():
pass
हे दर्शवते की एएसटी (AST) सुरुवातीपासून कसे तयार करायचे आणि नंतर त्यातून कोड कसा तयार करायचा. हा दृष्टीकोन कोड निर्मिती साधने आणि मेटाप्रोग्रामिंगसाठी (metaprogramming) शक्तिशाली आहे.
ast
मॉड्यूलचे व्यावहारिक अनुप्रयोग
ast
मॉड्यूलचे अनेक व्यावहारिक उपयोग आहेत, त्यामध्ये हे समाविष्ट आहे:
- कोड विश्लेषण: स्टाईलचे (style) उल्लंघन, सुरक्षा त्रुटी (security vulnerabilities) किंवा कार्यक्षमतेतील (performance) कमतरतांसाठी कोडचे विश्लेषण करणे. उदाहरणार्थ, तुम्ही एका मोठ्या प्रकल्पात कोडिंग स्टँडर्ड (coding standards) लागू करण्यासाठी एक साधन (tool) लिहू शकता.
- स्वयंचलित रीफॅक्टरिंग: व्हेरिएबलचे (variable) पुन:नामित करणे, पद्धती (methods) काढणे किंवा नवीन भाषा वैशिष्ट्ये वापरण्यासाठी कोड रूपांतरित (convert) करणे यासारखी कार्ये स्वयंचलित करणे. `rope` सारखी साधने शक्तिशाली रीफॅक्टरिंग क्षमतांसाठी एएसटीचा उपयोग करतात.
- स्टॅटिक विश्लेषण: कोड न चालवता (without running) संभाव्य त्रुटी (errors) किंवा बग (bugs) ओळखणे. `pylint` आणि `flake8` सारखी साधने समस्या शोधण्यासाठी एएसटी (AST) विश्लेषण वापरतात.
- कोड निर्मिती: टेम्पलेट्स (templates) किंवा विशिष्टतेवर आधारित आपोआप कोड तयार करणे. हे पुनरावृत्ती कोड (repetitive code) तयार करण्यासाठी किंवा विविध प्लॅटफॉर्मसाठी कोड तयार करण्यासाठी उपयुक्त आहे.
- भाषा विस्तार: पायथन कोडचे (Python code) भिन्न प्रतिनिधित्वात रूपांतर (transforming) करून कस्टम भाषा विस्तार किंवा डोमेन-विशिष्ट भाषा (DSLs) तयार करणे.
- सुरक्षा ऑडिटिंग: संभाव्य हानिकारक (harmful) रचना किंवा असुरक्षिततेसाठी कोडचे विश्लेषण करणे. हे असुरक्षित कोडिंग पद्धती ओळखण्यासाठी वापरले जाऊ शकते.
उदाहरण: कोडिंग स्टाईल (coding style) लागू करणे
असे समजूया की तुम्हाला तुमच्या प्रकल्पातील (project) सर्व फंक्शनची (function) नावे snake_case (उदा., my_function
ऐवजी myFunction
) या नियमाचे पालन (follow) करावे लागेल. तुम्ही उल्लंघनांसाठी तपासणी (check) करण्यासाठी ast
मॉड्यूल वापरू शकता.
import ast
import re
class SnakeCaseChecker(ast.NodeVisitor):
def __init__(self):
self.errors = []
def visit_FunctionDef(self, node):
if not re.match(r'^[a-z]+(_[a-z]+)*$', node.name):
self.errors.append(f"Function name '{node.name}' does not follow snake_case convention")
def check_code(self, code):
ast_tree = ast.parse(code)
self.visit(ast_tree)
return self.errors
# Example usage
code = """
def myFunction(x):
return x * 2
def calculate_area(width, height):
return width * height
"""
checker = SnakeCaseChecker()
errors = checker.check_code(code)
if errors:
for error in errors:
print(error)
else:
print("No style violations found")
हा कोड SnakeCaseChecker
क्लास परिभाषित (defines) करतो जो ast.NodeVisitor
कडून इनहेरिट करतो. visit_FunctionDef
मेथड फंक्शनचे नाव snake_case रेग्युलर एक्स्प्रेशनशी (regular expression) जुळते की नाही हे तपासते. नसल्यास, ते errors
लिस्टमध्ये एक त्रुटी संदेश (error message) जोडते. check_code
मेथड कोडचे विश्लेषण करते, एएसटी (AST) ट्रॅव्हर्स करते आणि त्रुटींची लिस्ट (list) परत करते.
ast
मॉड्यूल वापरताना सर्वोत्तम पद्धती
- एएसटीची (AST) रचना समजून घ्या: एएसटीमध्ये फेरफार करण्याचा प्रयत्न करण्यापूर्वी,
ast.dump()
वापरून त्याची रचना समजून घेण्यासाठी वेळ द्या. हे तुम्हाला ज्या नोडवर काम करायचे आहे ते ओळखण्यास मदत करेल. ast.NodeVisitor
आणिast.NodeTransformer
वापरा: हे वर्ग मॅन्युअली (manually) ट्रीमध्ये नॅव्हिगेट न करता एएसटी (AST) ट्रॅव्हर्स (traverse) आणि सुधारण्याचा एक सोपा मार्ग प्रदान करतात.- सखोलपणे (thoroughly) टेस्ट करा: एएसटीमध्ये बदल (modify) करताना, हे बदल योग्य आहेत आणि कोणतीही त्रुटी (error) देत नाहीत हे सुनिश्चित करण्यासाठी तुमच्या कोडची (code) पूर्णपणे चाचणी करा.
- कोड निर्मितीसाठी (code generation)
astunparse
विचारात घ्या:compile()
सुधारित कोड (modified code) एक्झिक्युट (execute) करण्यासाठी उपयुक्त आहे, तरastunparse
एएसटीमधून (AST) वाचनीय पायथन कोड (readable Python code) तयार करण्याचा एक मार्ग प्रदान करते. - प्रकार सूचना (Type Hints) वापरा: प्रकार सूचना तुमच्या कोडची सुलभता (readability) आणि देखभालक्षमता (maintainability) मोठ्या प्रमाणात सुधारू शकतात, विशेषत: जटिल एएसटी (AST) संरचनेसह (structures) कार्य करत असताना.
- तुमचा कोड (code) डॉक्युमेंट करा: कस्टम एएसटी व्हिजिटर्स (visitors) किंवा ट्रान्सफॉर्मर्स (transformers) तयार करताना, प्रत्येक मेथडचा (method) उद्देश आणि एएसटीमध्ये (AST) केलेले बदल स्पष्ट करण्यासाठी तुमचा कोड स्पष्टपणे डॉक्युमेंट (document) करा.
आव्हान (Challenges) आणि विचार
- जटिलता: एएसटी (AST) सोबत काम करणे, विशेषतः मोठ्या कोडबेससाठी (codebases) जटिल असू शकते. विविध नोड प्रकार (node types) आणि त्यांचे संबंध (relationships) समजून घेणे आव्हानात्मक असू शकते.
- देखभाल: एएसटी (AST) रचना पायथन व्हर्जनमध्ये (Python versions) बदलू शकतात. सुसंगतता (compatibility) सुनिश्चित करण्यासाठी तुमच्या कोडची (code) विविध पायथन व्हर्जनसह चाचणी (test) करा.
- कार्यक्षमता (performance): मोठ्या एएसटीचे (ASTs) ट्रॅव्हर्सिंग (traversing) आणि बदलणे (modifying) संथ (slow) असू शकते. कार्यक्षमता सुधारण्यासाठी तुमच्या कोडचे ऑप्टिमायझेशन (optimization) करण्याचा विचार करा. वारंवार ऍक्सेस (access) केलेले नोड कॅशिंग (caching) करणे किंवा अधिक कार्यक्षम अल्गोरिदम (algorithms) वापरणे उपयुक्त ठरू शकते.
- त्रुटी हाताळणी (error handling): एएसटी (AST) पार्स (parsing) किंवा फेरफार (manipulating) करताना त्रुटी चांगल्या प्रकारे हाताळा. वापरकर्त्याला माहितीपूर्ण त्रुटी संदेश (informative error messages) द्या.
- सुरक्षितता: एएसटीमधून (AST) तयार केलेला कोड (code) एक्झिक्युट (execute) करताना सावधगिरी बाळगा, विशेषत: जर एएसटी (AST) वापरकर्त्याच्या इनपुटवर आधारित असेल. कोड इंजेक्शन हल्ल्यांपासून (code injection attacks) बचाव करण्यासाठी इनपुट सॅनिटाईझ (sanitize) करा.
निष्कर्ष
पायथन ast
मॉड्यूल पायथन कोडच्या ॲब्स्ट्रॅक्ट सिंटॅक्स ट्रीसोबत (abstract syntax tree) संवाद साधण्याचा एक शक्तिशाली आणि लवचिक (flexible) मार्ग प्रदान करते. एएसटीची (AST) रचना समजून घेऊन आणि ast.NodeVisitor
आणि ast.NodeTransformer
क्लासेसचा वापर करून, तुम्ही प्रोग्रामॅटिकली (programmatically) पायथन कोडचे विश्लेषण, बदल आणि निर्मिती (generation) करू शकता. हे कोड विश्लेषण साधनांपासून (code analysis tools) ते स्वयंचलित रीफॅक्टरिंग (refactoring) आणि अगदी कस्टम भाषा विस्तारांपर्यंत (custom language extensions) विविध ऍप्लिकेशन्ससाठी (applications) एक नवीन संधी निर्माण करते. एएसटीसोबत (AST) काम करणे जटिल (complex) असू शकते, परंतु कोडमध्ये प्रोग्रामॅटिकली फेरफार (manipulating) करण्याची क्षमता असण्याचे फायदे महत्त्वपूर्ण आहेत. तुमच्या पायथन प्रकल्पांमध्ये (Python projects) नवीन शक्यता (possibilities) अनलॉक (unlock) करण्यासाठी ast
मॉड्यूलची शक्ती स्वीकारा.