Vegyünk egy kis “meta” – t a programozásról.
hogyan “tudja” a Python program(jobban tudja tolmácsként), hogyan kell futtatni a kódot?Ha még nem ismeri a programozást,úgy tűnhet, hogy magic.In tény, hogy még mindig varázslatnak tűnik számomra, miután több mint egy évtizede profi vagyok.
a Python tolmács nem varázslat(sajnálom, hogy csalódást okoztam).ez egy kiszámítható lépéskészletet követ, hogy lefordítsa a kódotaz utasításokba, amelyeket egy gép futtathat.
meglehetősen magas szinten a következő történik a kóddal:
- a kódot elemezzük (azaz felosztjuk) a darabok listájára, amelyet általában tokeneknek hívnak.Ezek a tokenek egy sor szabályon alapulnakolyan dolgokra, amelyeket másképp kell kezelni.Például a
if
kulcsszó más token, mint egy olyan numerikus érték, mint a42
. - a tokenek nyers listája átalakulegy absztrakt Szintaxisfa, az AST felépítéséhez, amelyet ebben a bejegyzésben többet fogunk megvizsgálni.Az AST olyan csomópontok gyűjteménye, amelyek a Python nyelv nyelvtanán alapulnak.Ne aggódjon, ha ennek most nincs értelme, mivel pillanatnyilag jobban megvilágítjuk.
- egy absztrakt szintaxisfából a tolmács alacsonyabb szintű utasításformát hozhat létre,amelyet bájtkódnak neveznek.Ezek az utasítások olyan dolgok, mint a
BINARY_ADD
, és nagyon általánosak ahhoz, hogy egy számítógép futtassa őket. - a rendelkezésre álló bytecode utasításokkal a tolmács végre futtathatja a kódot.A bájtkódot funkciók hívására használjákaz operációs rendszerben, amely végül kölcsönhatásba lép a CPU-val és a memóriávala program futtatásához.
sok további részlet beleférne ebbe a leírásba,de ez a durva vázlat arról, hogy a gépelt karaktereket hogyan hajtják végre a számítógépes CPU-k.
AST mint elemző eszköz
mire a forráskódod bytecode-vá változik, már túl késő ahhoz, hogy megértsd, amit írtál.Bytecode nagyon primitívés nagyon hangolt, hogy a tolmács fast.In más szavakkal, a bytecode az emberek feletti számítógépek számára készült.
másrészt az absztrakt szintaxisfáknak elegendő strukturált információjuk van bennükhogy hasznosak legyeneka kód megismeréséhez.Az ASTs még mindig nem túl emberbarát, de ésszerűbb, mint a bájtkód ábrázolása.
mivel a Python egy” batteries included ” nyelv,az ASTs használatához szükséges eszközök be vannak építve a standard könyvtárba.
az AST-kkel való munka elsődleges eszköze a ast
modul.Nézzünk meg egy példát, hogy lássuk, hogyan működik ez.
AST példa szerint
Az alábbiakban a példa Python szkriptet fogjuk használni.Ez a szkript válaszol arra a kérdésre, hogy”milyen modulokat importáltak?”
import astfrom pprint import pprintdef main():with open("ast_example.py", "r") as source:tree = ast.parse(source.read())
analyzer <span style="color:#f92672">=</span> Analyzer()analyzer<span style="color:#f92672">.</span>visit(tree)analyzer<span style="color:#f92672">.</span>report()
class Analyzer(ast.NodeVisitor):def init(self):self.stats = {“import”: , “from”: }
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">visit_Import</span>(self, node): <span style="color:#66d9ef">for</span> alias <span style="color:#f92672">in</span> node<span style="color:#f92672">.</span>names: self<span style="color:#f92672">.</span>stats<span style="color:#f92672">.</span>append(alias<span style="color:#f92672">.</span>name) self<span style="color:#f92672">.</span>generic_visit(node)<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">visit_ImportFrom</span>(self, node): <span style="color:#66d9ef">for</span> alias <span style="color:#f92672">in</span> node<span style="color:#f92672">.</span>names: self<span style="color:#f92672">.</span>stats<span style="color:#f92672">.</span>append(alias<span style="color:#f92672">.</span>name) self<span style="color:#f92672">.</span>generic_visit(node)<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">report</span>(self): pprint(self<span style="color:#f92672">.</span>stats)
if name == “main”:main()
Ez a kód néhány fontos dolgot csinál:
- egy Python fájl szövegét(ebben az esetben magát a példakódot)absztrakt szintaxisfává alakítja.
- elemzi az AST-t, hogy kivonjon belőle néhány információt.
ezt a kódot a következőképpen futtathatja:
$ python3 ast_example.py{'from': , 'import': }
átalakítás AST
with open("ast_example.py", "r") as source: tree = ast.parse(source.read())
két kódsorban olvasunk egy fájlt,és létrehozunk egy tree
nevű AST-t.A ast.parse
funkció teszi ezt egy pillanat alatt!Ennek a funkciónak a motorháztetője alatt rengeteg történik, amit boldogan figyelmen kívül hagyhatunk.
egy függvényhívással a Python feldolgozta az összes tokent, követte a nyelv összes szabályát, és felépített egy adatstruktúrát (pl., egy fa), amely tartalmazza az összes releváns információta kód futtatásához.
mielőtt továbblépnénk,Vegyünk egy pillanatra, hogy fontolja meg, mi a fa.A fák nagyon mély topicin szoftverfejlesztésígy ezt elsődlegesnek, nem pedig kimerítő magyarázatnak tekinti.
a fa az adatok tárolásának módjamint az “élek” által összekapcsolt “csomópontok” halmaza.”
+-----+ | A | +-----+ / \ / \+-----+ +-----+| B | | C |+-----+ +-----+
ebben a diagramban az A,B és C mind csomópontokés vannak élek, amelyek a-T B-hez és A-T C-hez kötik.
ennek a fának a kódban való ábrázolásának egyik módja lehet:
class Node: def __init__(self, value): self.value = value self.children = tree = Node('A')tree.children.append(Node('B'))tree.children.append(Node('C'))
figyeljük meg, hogy a tree
valójában egy csomópont!Amikor egy fával dolgozunk, valójában csomópontok gyűjteményével foglalkozunk, és a fa változó hivatkozás a “gyökér” csomópontra(pl. a csomópont).ilyen struktúrával ellenőrizhetjük a fa minden csomópontjátés cselekedjünk.Ezt úgy tesszük, hogy meglátogatjuk a fa minden csomópontjátés feldolgozzuk az adatait.
def print_node_value(value): print(value)def visit(node, handle_node): handle_node(node.value) for child in node.children: visit(child, handle_node)# tree is from the previous example.visit(tree, print_node_value)# This should print:# A# B# C
most,hogy van egy elképzelésünk arról, hogy mi a fa, megfontolhatjuk, hogy mit csinál a példa szkript következő szakasza.A Python absztrakt szintaxisfa faszerkezete jobban érintett a csomópontok száma és a tárolt adatok típusa miatt, mégis a csomópontok és az élek alapgondolata ugyanaz.
elemezze az AST-t
Miután megvan a fa,a Analyzer
követi a látogatói mintát, amelyet fent mutattamaz információ kinyerésére a fáról.
megjegyeztem, hogy a Python AST bonyolultabb, mint az alapvető Node
tervezés.Az egyik különbség az, hogy különböző típusú csomópontokat követ.Itt hasznos aast.NodeVisitor
.
a NodeVisitor
bármilyen típusú csomópontra válaszolhat a Pythonban AST.To látogasson el egy adott típusú csomópontra, meg kell valósítanunk egy módszertamely úgy néz ki, mint visit_<node type>
.
a példakódom megpróbálja kideríteni imports.To tudjon meg többet az importálásról, a kód a Import
és ImportFrom
csomóponttípusokból származik.
def visit_Import(self, node): for alias in node.names: self.stats.append(alias.name) self.generic_visit(node)def visit_ImportFrom(self, node): for alias in node.names: self.stats.append(alias.name) self.generic_visit(node)
Ez a kód a modul nevét veszi felés a statisztikák listájában tárolja.Bár a kód nem divatos, megmutatja, hogyan kell kölcsönhatásba lépniaz AST csomópontokkal.
aNodeVisitor
osztály definiálásával felhasználhatjuk a fa elemzésére.
analyzer = Analyzer()analyzer.visit(tree)
a visit
a módszer a visit_<node type>
metódust delegálja a visit_<node type>
találkozottmiközben áthalad a fa szerkezetén.
szóval, milyen típusú csomópont típusok vannak?A teljes listát a ast
modul dokumentációjában találhatja meg.Őszintén szólva, ezt a dokumentációt kissé nehéz felszívni.Lehet, hogy több sikerrel jár, ha egy kimerítőbb útmutatóra hivatkozik, mint például a zöld fa kígyók csomópontok útmutatója.
A
becsomagolása mostanra remélhetőleg megérti, hogyan kell:
- építsen egy AST-t a Python forráskódjából.
- végezzen elemzést az AST-n
NodeVisitor
használatával.
azt hiszem, sok érdekes kérdésre válaszolhata kódodrólelvont szintaxisfák használatával.Kérdések, mint:
- hány változót használtam?
- melyek a leggyakoribb függvényhívások a kódomban?
- a moduljaim szorosan kapcsolódnak egymáshoz?
- mely harmadik fél könyvtárai jelennek meg gyakran a különböző csomagokban?
a ast
modul valószínűleg nem olyan eszköz, amelyet nagyon often.In azokban az időkben, amikor szüksége van ast
, minimális API-ja meglehetősen emlékezetesés gyorsan elemezheti a kódot.
ha hasznosnak találta ezt, megosztaná ezt a Twitter-Envagy a kedvenc közösségi média webhelyén?Szeretek beszélgetni az emberekkel az ilyen témákrólígy nyugodtan tweetelj nekem a@mblayman oldalon.
tudj meg többet a Pythonról!
csatlakozhat a hírlevelemhez több mint 1000 fejlesztővel együtt, hogy segítsen többet megtudni a Django – ról és a Pythonról.