Python'ning ast moduli yordamida abstrak syntax daraxti manipulyatsiyasi imkoniyatlarini o'rganing. Python kodini dasturiy tahlil qilish, o'zgartirish va yaratishni o'rganing.
Python Ast Moduli: Abstrak Syntax Daraxti Manipulyatsiyasi Sirini Ochish
Python ast
moduli Python kodining abstrak syntax daraxti (AST) bilan o'zaro aloqa qilishning kuchli usulini taqdim etadi. AST - bu manba kodining sintaktik tuzilishining daraxt ko'rinishida ifodalanishi bo'lib, Python kodini dasturiy tahlil qilish, o'zgartirish va hatto yaratish imkonini beradi. Bu kod tahlili vositalari, avtomatlashtirilgan refaktoring, statik tahlil va hatto maxsus til kengaytmalari kabi turli xil ilovalarga yo'l ochadi. Ushbu maqola sizni ast
modulining asoslari bilan tanishtiradi, amaliy misollar va uning imkoniyatlari haqida tushunchalar beradi.
Abstrak Syntax Daraxti (AST) nima?
ast
moduliga sho'ng'ishdan oldin, keling, Abstrak Syntax Daraxti nima ekanligini tushunaylik. Python tarjimoni kodingizni bajarganda, birinchi qadam kodni ASTga ajratishdir. Ushbu daraxt tuzilishi kodning sintaktik elementlarini, masalan, funktsiyalar, sinflar, tsikllar, ifodalar va operatorlar, shuningdek ularning o'zaro munosabatlarini ifodalaydi. AST bo'shliqlar va izohlar kabi keraksiz tafsilotlarni tashlab, asosiy strukturaviy ma'lumotlarga e'tibor qaratadi. Kodni shu tarzda ifodalash orqali dasturlar kodni o'zi tahlil qilishi va manipulyatsiya qilishi mumkin, bu ko'p hollarda juda foydali.
ast
Moduli bilan Ishlashni Boshlash
ast
moduli Pythonning standart kutubxonasining bir qismidir, shuning uchun sizga qo'shimcha paketlarni o'rnatish kerak emas. Undan foydalanishni boshlash uchun shunchaki import qiling:
import ast
ast
modulining asosiy funktsiyasi ast.parse()
bo'lib, u Python kodining satrini kiritish sifatida qabul qiladi va AST ob'ektini qaytaradi.
code = """
def add(x, y):
return x + y
"""
ast_tree = ast.parse(code)
print(ast_tree)
Bu shunga o'xshash narsani chiqaradi: <_ast.Module object at 0x...>
. Ushbu natija ayniqsa informativ bo'lmasa-da, kodning ASTga muvaffaqiyatli ajratilganligini ko'rsatadi. ast_tree
ob'ekti endi ajratilgan kodning butun tuzilishini o'z ichiga oladi.
ASTni O'rganish
AST tuzilishini tushunish uchun biz ast.dump()
funktsiyasidan foydalanishimiz mumkin. Ushbu funktsiya daraxt bo'ylab rekursiv ravishda harakat qiladi va har bir tugunning batafsil ko'rinishini chop etadi.
code = """
def add(x, y):
return x + y
"""
ast_tree = ast.parse(code)
print(ast.dump(ast_tree, indent=4))
Natija quyidagicha bo'ladi:
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=[]
)
Ushbu natija kodning ierarxik tuzilishini ko'rsatadi. Keling, uni qismlarga ajratamiz:
Module
: Butun modulni ifodalovchi ildiz tugun.body
: Modul ichidagi bayonotlar ro'yxati.FunctionDef
: Funktsiya ta'rifini ifodalaydi. Uning atributlariga quyidagilar kiradi:name
: Funktsiya nomi ('add').args
: Funktsiya argumentlari.arguments
: Funktsiya argumentlari haqida ma'lumotni o'z ichiga oladi.arg
: Yagona argumentni ifodalaydi (masalan, 'x', 'y').body
: Funktsiya tanasi (bayonotlar ro'yxati).Return
: Qaytarish bayonotini ifodalaydi.value
: Qaytariladigan qiymat.BinOp
: Ikkilik operatsiyani ifodalaydi (masalan, x + y).left
: Chap operand (masalan, 'x').op
: Operator (masalan, 'Add').right
: O'ng operand (masalan, 'y').
AST Bo'ylab Harakatlanish
ast
moduli AST bo'ylab harakatlanish uchun ast.NodeVisitor
sinfini taqdim etadi. ast.NodeVisitor
sinfini kichiklashtirish va uning usullarini bekor qilish orqali siz traversal paytida duch keladigan o'ziga xos tugun turlarini qayta ishlashingiz mumkin. Bu kod tuzilishini tahlil qilish, o'ziga xos naqshlarni aniqlash yoki ma'lumotni olish uchun foydalidir.
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) # Natija: ['add', 'subtract']
Ushbu misolda FunctionNameExtractor
ast.NodeVisitor
dan meros bo'lib o'tadi va visit_FunctionDef
usulini bekor qiladi. Ushbu usul ASTdagi har bir funktsiya ta'rifi tuguni uchun chaqiriladi. Usul funktsiya nomini function_names
ro'yxatiga qo'shadi. visit()
usuli AST traversalini boshlaydi.
Misol: Barcha o'zgaruvchilarga qiymat berishni topish
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) # Natija: ['x', 'y', 'message']
Ushbu misol kodda barcha o'zgaruvchilarga qiymat berishni topadi. visit_Assign
usuli har bir qiymat berish bayonoti uchun chaqiriladi. U vazifaning maqsadlari bo'ylab iteratsiya qiladi va agar maqsad oddiy nom bo'lsa (ast.Name
), u nomni assignments
ro'yxatiga qo'shadi.
ASTni O'zgartirish
ast
moduli sizga ASTni o'zgartirishga ham imkon beradi. Siz mavjud tugunlarni o'zgartirishingiz, yangi tugunlarni qo'shishingiz yoki tugunlarni butunlay olib tashlashingiz mumkin. ASTni o'zgartirish uchun ast.NodeTransformer
sinfidan foydalanasiz. ast.NodeVisitor
ga o'xshash, siz ast.NodeTransformer
ni kichiklashtirasiz va o'ziga xos tugun turlarini o'zgartirish uchun uning usullarini bekor qilasiz. Asosiy farq shundaki, ast.NodeTransformer
usullari o'zgartirilgan tugunni (yoki uni almashtirish uchun yangi tugunni) qaytarishi kerak. Agar usul None
ni qaytarsa, tugun ASTdan olib tashlanadi.
ASTni o'zgartirgandan so'ng, compile()
funktsiyasi yordamida uni qayta ishlaydigan Python kodiga kompilyatsiya qilishingiz kerak.
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, '', 'exec')
# O'zgartirilgan kodni bajarish
exec(new_code)
print(x) # Natija: 11
print(y) # Natija: 21
Ushbu misolda AddOneTransformer
ast.NodeTransformer
dan meros bo'lib o'tadi va visit_Num
usulini bekor qiladi. Ushbu usul har bir sonli literal tugun (ast.Num
) uchun chaqiriladi. Usul qiymati 1 ga oshirilgan yangi ast.Num
tugunini yaratadi. visit()
usuli o'zgartirilgan ASTni qaytaradi.
compile()
funktsiyasi o'zgartirilgan ASTni, fayl nomini (bu holda <string>
, kod satrdan kelganligini ko'rsatadi) va bajarish rejimini (kod blokini bajarish uchun 'exec'
) oladi. U exec()
funktsiyasi yordamida bajarilishi mumkin bo'lgan kod ob'ektini qaytaradi.
Misol: O'zgaruvchi nomini almashtirish
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, '', 'exec')
# O'zgartirilgan kodni bajarish
exec(new_code)
Ushbu misol 'number'
o'zgaruvchi nomining barcha holatlarini 'num'
ga almashtiradi. VariableNameReplacer
eski va yangi nomlarni argument sifatida oladi. visit_Name
usuli har bir nom tuguni uchun chaqiriladi. Agar tugunning identifikatori eski nomga mos kelsa, u yangi nom va bir xil kontekstga ega (node.ctx
) yangi ast.Name
tugunini yaratadi. Kontekst nomning qanday ishlatilishini ko'rsatadi (masalan, yuklash, saqlash).
ASTdan Kod Yaratish
compile()
ASTdan kodni bajarishga imkon bersa-da, u kodni satr sifatida olish usulini taqdim etmaydi. ASTdan Python kodini yaratish uchun siz astunparse
kutubxonasidan foydalanishingiz mumkin. Ushbu kutubxona standart kutubxonaning bir qismi emas, shuning uchun uni avval o'rnatishingiz kerak:
pip install astunparse
Keyin, ASTdan kodni yaratish uchun astunparse.unparse()
funktsiyasidan foydalanishingiz mumkin.
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)
Natija quyidagicha bo'ladi:
def add(x, y):
return (x + y)
Eslatma: (x + y)
atrofidagi qavslar to'g'ri operator ustunligini ta'minlash uchun astunparse
tomonidan qo'shiladi. Ushbu qavslar qat'iy zarur bo'lmasligi mumkin, ammo ular kodning to'g'riligini kafolatlaydi.
Misol: Oddiy sinf yaratish
import ast
import astunparse
class_name = 'MyClass'
method_name = 'my_method'
# Sinf ta'rifi tugunini yaratish
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=[]
)
# Sinf ta'rifini o'z ichiga olgan modul tugunini yaratish
module = ast.Module(body=[class_def], type_ignores=[])
# Kodni yaratish
code = astunparse.unparse(module)
print(code)
Ushbu misol quyidagi Python kodini yaratadi:
class MyClass:
def my_method():
pass
Bu ASTni noldan qanday qurish va keyin undan kodni yaratishni ko'rsatadi. Ushbu yondashuv kodni yaratish vositalari va metaprogrammalash uchun kuchli.
ast
Modulining Amaliy Ilovalari
ast
modulida ko'plab amaliy ilovalar mavjud, jumladan:
- Kod Tahlili: Kodni uslub buzilishlari, xavfsizlik zaifliklari yoki ishlashning tor joylari uchun tahlil qilish. Misol uchun, siz katta loyihada kodlash standartlarini majburlash uchun vosita yozishingiz mumkin.
- Avtomatlashtirilgan Refaktoring: O'zgaruvchilarni qayta nomlash, usullarni chiqarib olish yoki kodni yangi til xususiyatlaridan foydalanishga aylantirish kabi vazifalarni avtomatlashtirish.
rope
kabi vositalar kuchli refaktoring imkoniyatlari uchun ASTlardan foydalanadi. - Statik Tahlil: Kodni ishga tushirmasdan, undagi potentsial xatolar yoki xatoliklarni aniqlash.
pylint
vaflake8
kabi vositalar muammolarni aniqlash uchun AST tahlilidan foydalanadi. - Kod Yaratish: Kodni shablonlar yoki spetsifikatsiyalar asosida avtomatik ravishda yaratish. Bu takroriy kodni yaratish yoki turli platformalar uchun kodni yaratish uchun foydalidir.
- Til Kengaytmalari: Python kodini turli xil ko'rinishlarga aylantirish orqali maxsus til kengaytmalarini yoki domenga xos tillarni (DSL) yaratish.
- Xavfsizlik Audit: Kodni potentsial zararli konstruksiyalar yoki zaifliklar uchun tahlil qilish. Bu xavfsiz bo'lmagan kodlash amaliyotlarini aniqlash uchun ishlatilishi mumkin.
Misol: Kodlash Uslubini Majburlash
Deylik, siz loyihangizdagi barcha funktsiya nomlari ilon_holati konventsiyasiga (masalan, my_function
o'rniga myFunction
) rioya qilishini ta'minlamoqchisiz. Buzilishlarni tekshirish uchun ast
modulidan foydalanishingiz mumkin.
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
# Misol foydalanish
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("Uslub buzilishlari topilmadi")
Ushbu kod ast.NodeVisitor
dan meros bo'lib o'tgan SnakeCaseChecker
sinfini belgilaydi. visit_FunctionDef
usuli funktsiya nomi ilon_holati regexiga mos keladimi yoki yo'qligini tekshiradi. Agar mos kelmasa, u errors
ro'yxatiga xato xabarini qo'shadi. check_code
usuli kodni ajratadi, AST bo'ylab harakat qiladi va xatolar ro'yxatini qaytaradi.
ast
Moduli bilan Ishlashda Eng Yaxshi Amaliyotlar
- AST Tuzilishini Tushuning: ASTni manipulyatsiya qilishga urinishdan oldin,
ast.dump()
yordamida uning tuzilishini tushunish uchun vaqt ajrating. Bu sizga ishlashingiz kerak bo'lgan tugunlarni aniqlashga yordam beradi. ast.NodeVisitor
vaast.NodeTransformer
dan Foydalaning: Ushbu sinflar daraxt bo'ylab qo'lda harakatlanishingizga hojat qoldirmasdan, AST bo'ylab harakatlanish va o'zgartirishning qulay usulini taqdim etadi.- Yaxshilab Sinovdan O'tkazing: ASTni o'zgartirganda, o'zgarishlarning to'g'riligini va hech qanday xatolikka yo'l qo'ymasligini ta'minlash uchun kodingizni yaxshilab sinovdan o'tkazing.
- Kod Yaratish uchun
astunparse
ni Ko'rib Chiqing:compile()
o'zgartirilgan kodni bajarish uchun foydali bo'lsa-da,astunparse
ASTdan o'qilishi mumkin bo'lgan Python kodini yaratish usulini taqdim etadi. - Turli Maslahatlar: Turli maslahatlar kodingizning o'qilishini va saqlanishini sezilarli darajada yaxshilashi mumkin, ayniqsa murakkab AST tuzilmalari bilan ishlaganda.
- Kodingizni Hujjatlashtiring: Maxsus AST tashrif buyuruvchilari yoki transformatorlarini yaratganda, har bir usulning maqsadini va ASTga kiritadigan o'zgarishlarni tushuntirish uchun kodingizni aniq hujjatlashtiring.
Qiyinchiliklar va Mulohazalar
- Murakkablik: ASTlar bilan ishlash murakkab bo'lishi mumkin, ayniqsa katta kod bazalari uchun. Turli xil tugun turlarini va ularning o'zaro munosabatlarini tushunish qiyin bo'lishi mumkin.
- Xizmat Ko'rsatish: AST tuzilmalari Python versiyalari orasida o'zgarishi mumkin. Muvofiqlikni ta'minlash uchun kodingizni turli Python versiyalari bilan sinovdan o'tkazishni unutmang.
- Ishlash: Katta ASTlar bo'ylab harakatlanish va ularni o'zgartirish sekin bo'lishi mumkin. Ishlashni yaxshilash uchun kodingizni optimallashtirishni ko'rib chiqing. Tez-tez ishlatiladigan tugunlarni keshlash yoki undan ham samaraliroq algoritmlardan foydalanish yordam berishi mumkin.
- Xatolarni Boshqarish: ASTni ajratish yoki manipulyatsiya qilishda xatolarni nozik tarzda hal qiling. Foydalanuvchiga informativ xato xabarlarini taqdim eting.
- Xavfsizlik: ASTdan yaratilgan kodni bajarishda ehtiyot bo'ling, ayniqsa AST foydalanuvchi kiritishiga asoslangan bo'lsa. Kod in'ektsiyasi hujumlarining oldini olish uchun kirishni tozalang.
Xulosa
Python ast
moduli Python kodining abstrak syntax daraxti bilan o'zaro aloqa qilishning kuchli va moslashuvchan usulini taqdim etadi. AST tuzilishini tushunish va ast.NodeVisitor
va ast.NodeTransformer
sinflaridan foydalanish orqali siz Python kodini dasturiy tahlil qilishingiz, o'zgartirishingiz va yaratishingiz mumkin. Bu kod tahlili vositalaridan tortib, avtomatlashtirilgan refaktoring va hatto maxsus til kengaytmalarigacha bo'lgan keng ko'lamli ilovalarga yo'l ochadi. ASTlar bilan ishlash murakkab bo'lishi mumkin bo'lsa-da, kodni dasturiy manipulyatsiya qila olishning afzalliklari sezilarli. Python loyihalaringizda yangi imkoniyatlarni ochish uchun ast
modulining kuchini o'zlashtiring.