Buka Kunci Kuasa Tersembunyi Python: Kuasai Pokok Sintaks Abstrak untuk Sihir Kod

Linda Hamilton
Lepaskan: 2024-11-22 07:41:10
asal
458 orang telah melayarinya

Unlock Python

Keupayaan pengaturcaraan meta Python cukup hebat, dan Abstract Syntax Trees (AST) membawanya ke tahap yang baharu. Saya telah bermain-main dengan AST sejak kebelakangan ini, dan saya teruja untuk berkongsi apa yang telah saya pelajari.

Pada terasnya, AST ialah perwakilan seperti pokok bagi struktur kod Python anda. Ia seperti melihat kod anda melalui lensa yang berbeza, di mana setiap bahagian program anda menjadi nod dalam pokok ini. Perkara yang menarik ialah, anda boleh memanipulasi pokok ini untuk mengubah cara kod anda berkelakuan.

Mari kita mulakan dengan contoh mudah. Katakan kami mempunyai sekeping kod ini:

x = 5 + 3
print(x)
Salin selepas log masuk
Salin selepas log masuk

Apabila kita menghuraikan ini menjadi AST, ia kelihatan seperti ini:

import ast

code = """
x = 5 + 3
print(x)
"""

tree = ast.parse(code)
print(ast.dump(tree))
Salin selepas log masuk
Salin selepas log masuk

Ini akan mengeluarkan perwakilan AST. Ia agak tidak kemas, tetapi anda boleh melihat bagaimana setiap bahagian kod kami diwakili sebagai nod dalam pepohon.

Sekarang, mengapa ini berguna? Nah, ia membolehkan kita melakukan beberapa helah yang cukup kemas. Kami boleh menganalisis kod, mengubah suainya, atau menjana kod baharu dengan cepat. Ia seperti mempunyai penglihatan sinar-X untuk program Python anda.

Salah satu perkara paling hebat yang boleh anda lakukan dengan AST ialah mencipta ciri bahasa tersuai. Bayangkan anda sedang mengusahakan projek data besar, dan anda bosan menulis kod boilerplate yang sama untuk pengesahan data. Dengan AST, anda boleh mencipta penghias tersuai yang menambahkan kod pengesahan secara automatik pada fungsi anda.

Berikut ialah contoh mudah:

import ast
import inspect

def validate_types(func):
    source = inspect.getsource(func)
    tree = ast.parse(source)

    for node in ast.walk(tree):
        if isinstance(node, ast.FunctionDef):
            for arg in node.args.args:
                if arg.annotation:
                    check = ast.parse(f'if not isinstance({arg.arg}, {arg.annotation.id}): raise TypeError("Invalid type for {arg.arg}")').body[0]
                    node.body.insert(0, check)

    new_func = compile(ast.fix_missing_locations(tree), '<string>', 'exec')
    namespace = {}
    exec(new_func, namespace)
    return namespace[func.__name__]

@validate_types
def greet(name: str, times: int):
    for _ in range(times):
        print(f"Hello, {name}!")

greet("Alice", 3)  # This works
greet("Bob", "not a number")  # This raises a TypeError
Salin selepas log masuk
Salin selepas log masuk

Dalam contoh ini, kami telah mencipta penghias yang secara automatik menambah semakan jenis pada fungsi kami. Ia menghuraikan fungsi ke dalam AST, menambah kod semakan jenis untuk setiap hujah beranotasi, dan kemudian menyusun semula fungsi tersebut. Agak hebat, bukan?

Tetapi kami hanya menconteng permukaan di sini. AST boleh digunakan untuk semua jenis perkara. Pengoptimuman kod adalah satu lagi yang besar. Anda boleh menulis pengubah AST yang mencari corak tertentu dalam kod anda dan menggantikannya dengan versi yang lebih cekap.

Sebagai contoh, katakan anda sedang bekerja dengan banyak rangkaian rentetan dalam kod anda. Anda tahu bahawa menggunakan join() selalunya lebih pantas daripada operator untuk rentetan, terutamanya apabila berurusan dengan banyak rentetan. Anda boleh menulis pengubah AST yang menukar gabungan rentetan secara automatik untuk menyertai() panggilan:

import ast

class StringConcatOptimizer(ast.NodeTransformer):
    def visit_BinOp(self, node):
        if isinstance(node.op, ast.Add) and isinstance(node.left, ast.Str) and isinstance(node.right, ast.Str):
            return ast.Call(
                func=ast.Attribute(
                    value=ast.Str(s=''),
                    attr='join',
                    ctx=ast.Load()
                ),
                args=[
                    ast.List(
                        elts=[node.left, node.right],
                        ctx=ast.Load()
                    )
                ],
                keywords=[]
            )
        return node

# Usage
code = """
result = "Hello, " + "world!"
"""

tree = ast.parse(code)
optimizer = StringConcatOptimizer()
optimized_tree = optimizer.visit(tree)

print(ast.unparse(optimized_tree))
# Output: result = ''.join(['Hello, ', 'world!'])
Salin selepas log masuk

Pengubah ini mencari operasi penggabungan rentetan dan menggantikannya dengan panggilan join(). Ini contoh mudah, tetapi anda boleh bayangkan betapa hebatnya ini untuk pangkalan kod yang lebih besar.

AST juga bagus untuk analisis statik. Anda boleh menulis alat yang mengimbas kod anda untuk kemungkinan pepijat, pelanggaran gaya atau kelemahan keselamatan. Banyak alat linting popular menggunakan AST di bawah hud untuk menganalisis kod anda.

Berikut ialah contoh mudah bagaimana anda boleh menggunakan AST untuk mencari semua definisi fungsi dalam sekeping kod:

x = 5 + 3
print(x)
Salin selepas log masuk
Salin selepas log masuk

Fungsi ini menghuraikan kod ke dalam AST, kemudian berjalan melalui pepohon mencari nod FunctionDef. Ini contoh mudah, tetapi anda boleh melihat cara ini boleh dilanjutkan untuk melakukan analisis yang lebih kompleks.

Satu bidang yang AST benar-benar bersinar ialah dalam mencipta bahasa khusus domain (DSL). Ini adalah bahasa yang disesuaikan untuk tugas atau domain tertentu. Dengan AST, anda boleh menghuraikan bahasa tersuai ini dan menterjemahkannya ke dalam kod Python.

Sebagai contoh, katakan anda sedang mengusahakan projek analisis data dan anda ingin mencipta bahasa mudah untuk mentakrifkan transformasi data. Anda boleh menggunakan AST untuk menghuraikan bahasa ini dan menjana kod Python:

import ast

code = """
x = 5 + 3
print(x)
"""

tree = ast.parse(code)
print(ast.dump(tree))
Salin selepas log masuk
Salin selepas log masuk

Penghuraikan ini mengambil DSL mudah untuk transformasi data dan menukarnya kepada kod Python menggunakan panda. Ini adalah contoh asas, tetapi ia menunjukkan cara anda boleh menggunakan AST untuk mencipta bahasa mini anda sendiri yang disesuaikan dengan keperluan khusus anda.

AST juga amat berguna untuk pemfaktoran semula kod. Anda boleh menulis alatan yang mengemas kini kod anda secara automatik untuk mengikut corak atau konvensyen baharu. Sebagai contoh, katakan anda ingin mengemas kini semua penyata cetakan anda untuk menggunakan f-strings:

import ast
import inspect

def validate_types(func):
    source = inspect.getsource(func)
    tree = ast.parse(source)

    for node in ast.walk(tree):
        if isinstance(node, ast.FunctionDef):
            for arg in node.args.args:
                if arg.annotation:
                    check = ast.parse(f'if not isinstance({arg.arg}, {arg.annotation.id}): raise TypeError("Invalid type for {arg.arg}")').body[0]
                    node.body.insert(0, check)

    new_func = compile(ast.fix_missing_locations(tree), '<string>', 'exec')
    namespace = {}
    exec(new_func, namespace)
    return namespace[func.__name__]

@validate_types
def greet(name: str, times: int):
    for _ in range(times):
        print(f"Hello, {name}!")

greet("Alice", 3)  # This works
greet("Bob", "not a number")  # This raises a TypeError
Salin selepas log masuk
Salin selepas log masuk

Transformer ini mencari pernyataan cetakan menggunakan %-formatting lama dan menukarkannya kepada menggunakan f-strings. Ia agak rumit kerana ia perlu mengendalikan kes yang berbeza, tetapi ia menunjukkan kuasa AST untuk pemfaktoran semula automatik.

Satu perkara yang perlu diingat semasa bekerja dengan AST ialah ia boleh menjadi agak cerewet. Anda perlu memastikan semua nod dalam AST anda disediakan dengan betul, atau anda akan mendapat ralat apabila anda cuba menyusun atau melaksanakan kod tersebut. Fungsi ast.fix_missing_locations() ialah rakan anda di sini – ia mengisi sebarang maklumat kedudukan yang hilang dalam AST anda.

Selain itu, walaupun AST berkuasa, ia tidak selalunya alat terbaik untuk tugas itu. Untuk manipulasi rentetan mudah atau perubahan berasaskan regexp, anda mungkin lebih baik menggunakan kaedah yang lebih mudah. AST bersinar apabila anda perlu memahami atau memanipulasi struktur kod itu sendiri.

Kesimpulannya, Pokok Sintaks Abstrak ialah alat yang berkuasa dalam kit alat pengaturcaraan meta Python anda. Mereka membenarkan anda menganalisis, mengubah dan menjana kod dengan cara yang sukar atau mustahil dengan kaedah lain. Sama ada anda mengoptimumkan prestasi, mencipta ciri bahasa tersuai atau membina alatan untuk analisis kod dan pemfaktoran semula, AST memberi anda kuasa untuk bekerja dengan kod Python pada tahap asas. Ia seperti mempunyai kuasa besar untuk program Python anda!


Ciptaan Kami

Pastikan anda melihat ciptaan kami:

Pusat Pelabur | Hidup Pintar | Epos & Gema | Misteri Membingungkan | Hindutva | Pembangunan Elit | Sekolah JS


Kami berada di Medium

Tech Koala Insights | Dunia Epok & Gema | Medium Pusat Pelabur | Medium Misteri Membingungkan | Sains & Zaman Sederhana | Hindutva Moden

Atas ialah kandungan terperinci Buka Kunci Kuasa Tersembunyi Python: Kuasai Pokok Sintaks Abstrak untuk Sihir Kod. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan