pojďme si trochu „meta“ o programování.
Jak program Python (lépe známý jako interpret) „ví“, jak spustit kód?Pokud jste v programování nováčkem,může se to zdát magic.In fakt, stále mi to připadá jako magiepo tom, že jsem profesionálpo více než deset let.
interpret Pythonu není kouzelný(Omlouvám se, že vás zklamám). následuje předvídatelná sada kroků k překladu kódu do instrukcí, které může stroj spustit.
na poměrně vysoké úrovni, tady je to, co se stane s vaším kódem:
- kód je analyzován (tj.Tyto žetony jsou založeny na souboru pravidelpro věci, s nimiž by se mělo zacházet odlišně.Například,klíčové slovo
if
je jiný projev, než číselná hodnota jako42
. - surový seznam tokenů je transformovánpro vytvoření abstraktního Syntaxového stromu, AST, což je předmět, který budeme zkoumat více v tomto příspěvku.AST je sbírka uzlů, které jsou propojeny na základě gramatiky jazyka Python.Nebojte se, pokud to teď nedává smysl, protože na to na okamžik posvítíme více světla.
- z abstraktního syntaxového stromu může interpret vytvořit formu instrukcí nižší úrovně nazvanou bytecode.Tyto pokyny jsou věci jako
BINARY_ADD
a mají být velmi generické, aby je počítač mohl spustit. - s dostupnými instrukcemi bytecode může interpret konečně spustit váš kód.Bytecode se používá k volání funkcív operačním systémukterý bude nakonec interagovat s CPU a pamětí pro spuštění programu.
do tohoto popisu by se mohlo vejít mnoho dalších podrobností, ale to je hrubý náčrt toho, jak jsou zadané znaky prováděny počítačovými procesory.
jako nástroje pro analýzu
v době, kdy je zdrojový kód změněn na bytecode, je příliš pozdě na to, abyste získali mnoho porozumění o tom, co jste napsali.Bytecode je velmi primitivní a velmi naladěný na výrobu tlumočníka fast.In jinými slovy, bytecode je určen pro počítače nad lidmi.
Na druhou stranu,abstraktní syntaktické stromy mají dost strukturovaný informationwithin jim, aby jim usefulfor učení o vašem kódu.Ast stále nejsou příliš přátelští lidé, ale jsou rozumnější než reprezentace bytecode.
protože Python je jazyk“ včetně baterií“, nástroje, které potřebujete použít, jsou zabudovány do standardní knihovny.
primárním nástrojem pro práci s AST je modul ast
.Podívejme se na příklad, abychom zjistili, jak to funguje.
AST podle příkladu
níže je uveden příklad Python skript, který budeme používat.Tento skript odpovídá na otázku “ jaké moduly byly importovány?“
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()
Tento kód má pár hlavních věcí:
- Transformuje soubor s příponou Python text(v tomto případě, například kód sám o sobě)na abstraktní syntaktický strom.
- analyzuje AST a extrahuje z něj některé informace.
tento kód můžete spustit jako:
$ python3 ast_example.py{'from': , 'import': }
Transformovat do AST
with open("ast_example.py", "r") as source: tree = ast.parse(source.read())
Ve dvou řádků kódu,četli jsme soubor a vytvořit AST jménem tree
.Funkce ast.parse
je to hračka!Pod kapotou této funkce se děje Tuna, kterou můžeme blaženě ignorovat.
S jedním voláním funkce zpracoval Python všechny tokeny, dodržoval všechna pravidla jazyka a vytvořil datovou strukturu (tj., strom) obsahující všechny relevantní informacek spuštění kódu.
než se přesuneme, pojďme chvíli zvážit, co je strom.Stromy jsou velmi hlubokým tématem vývoje softwaru, takže to považujte za primerspíše než za vyčerpávající vysvětlení.
strom je způsob, jak držet dataas soubor „uzly“ spojeny „hrany.“
+-----+ | A | +-----+ / \ / \+-----+ +-----+| B | | C |+-----+ +-----+
V tomto diagramu,A, B, a C jsou všechny nodesand tam jsou hrany spojující z A do B a C.
Jeden způsob, jak reprezentovat tomto stromu v kódu by mohlo být:
class Node: def __init__(self, value): self.value = value self.children = tree = Node('A')tree.children.append(Node('B'))tree.children.append(Node('C'))
Všimněte si, že tree
je vlastně uzel!Když pracujeme se stromem,máme opravdu co do činění s kolekcí uzlů,a strom proměnné je odkaz na „kořenový“ uzel(např. uzlu).Tím, že má takovou strukturu,můžeme kontrolovat každý uzel v treeand jednat.Děláme to tím, že navštívíme každý uzel ve stromua zpracováváme jeho data.
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
Nyní, když máme představu o tom, co je strom,můžeme zvážit, jaké další sectionof příklad skriptu.Stromová struktura abstraktního syntaxního stromu Pythonu je více zapojena kvůli počtu uzlů a typu uložených dat, ale základní myšlenka uzlů a hran je stejná.
Analyzovat AST
Jakmile budeme mít strom, Analyzer
sleduje návštěvník patternthat ukázal jsem aboveto extrahovat informace ze stromu.
poznamenal jsem, že Python AST je složitější než můj základní Node
design.Jedním rozdílem je, že sleduje různé typy uzlů.Zde je užitečné ast.NodeVisitor
.
NodeVisitor
mohou reagovat na jakýkoli typ nodein Pythonu AST.Navštívit určitý typ uzlu,musíme zavést methodthat vypadá jako visit_<node type>
.
Můj příklad kódu se snaží, aby se dozvěděl dovozu.Dozvědět se o dovoz,kód táhne od Import
ImportFrom
typy uzlů.
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)
Tento kód má název moduleand obchodech itin seznam statistiky.Zatímco kód není fantazijní, ukazuje vám, jak interagovats uzly AST.
s definovanou třídou NodeVisitor
ji můžeme použít k analýze stromu.
analyzer = Analyzer()analyzer.visit(tree)
visit
metoda bude delegovat na své visit_<node type>
methodwhenever, že typ uzlu je encounteredwhile procházející přes strukturu stromu.
jaké typy uzlů existují?Úplný seznam najdete v sekci gramatiky ast
dokumentace modulu .Po pravdě řečeno, zdá se mi, že dokumentace je trochu těžko absorbovatelná.Možná budete mít větší úspěchpomocí vyčerpávajícího průvodce, jako je theGreen Tree Snakes Nodes guide.
zabalení
nyní snad pochopíte, jak:
- vytvořit AST ze zdrojového kódu Pythonu.
- proveďte analýzu na AST pomocí
NodeVisitor
.
myslím, že můžete odpovědět na mnoho zajímavých otázeko vašem kódupomocí abstraktních syntaxových stromů.Otázky jako:
- kolik proměnných jsem použil?
- jaké jsou nejčastější volání funkcí v mém kódu?
- Jsou mé moduly pevně spojeny?
- které knihovny třetích stran se často zobrazují v různých balíčcích?
ast
modul asi není toolthat budete dosáhnout velmi často.V těch časech, že je třeba ast
,jeho minimální API je poměrně memorableand můžete analyzovat kód rychle.
Pokud vám to připadá užitečné, nevadilo by vám to sdílet na Twitteronebo na vašem oblíbeném webu sociálních médií?Líbí se mi chatování s peopleabout tyto druhy témattak neváhejte mě tweet na@mblayman.
další informace o Pythonu!
můžete připojit se k mé newsletter spolu s 1,000+ ostatními vývojáři, aby vám pomohou dozvědět se více o Django a Python.