Matt Layman

Let ’ s get a little ”meta” about programming.

miten Python-ohjelma(tunnetaan paremmin tulkkina)”osaa” suorittaa koodisi?Jos olet uusi ohjelmoinnissa, se voi tuntua magic.In itse asiassa, se tuntuu edelleen taikaa minulle jälkeen on ammatillinen yli vuosikymmenen.

Python-tulkki ei ole taikaa(pahoittelen pettymystä).se seuraa ennalta arvattavia askelia koodisi kääntämiseksi ohjeiksi, joita kone voi käyttää.

melko korkealla tasolla,näin käy koodillesi:

  1. koodi jäsennetään (eli pilkotaan) listaksi kappaleista, joita yleensä kutsutaan poleteiksi.Nämä poletit perustuvat sääntöihin asioista, joita tulisi kohdella eri tavalla.Esimerkiksi avainsana if on eri merkki kuin numeerinen arvo, kuten 42.
  2. rahakkeiden raakaluettelo muunnetaan rakentamaan Abstrakti Syntaksipuu, AST,jota tässä viestissä tarkastellaan tarkemmin.AST on kokoelma nodeja, jotka liittyvät toisiinsa Python-kielen kieliopin perusteella.Älä huoli, jos siinä ei ole mitään järkeä, koska valotamme sitä hetken kuluttua.
  3. abstraktista syntaksipuusta tulkitsija voi tuottaa alemman tason ohjemuodon,jota kutsutaan bytekoodiksi.Nämä ohjeet ovat sellaisia asioita kuin BINARY_ADDja niiden on tarkoitus olla hyvin yleisluontoisia, että tietokone voi niitä ajaa.
  4. käytettävissä olevien bytecode-ohjeiden avulla tulkki voi lopulta suorittaa koodisi.Bytecode käytetään kutsumaan toimintoja käyttöjärjestelmässäsi, joka lopulta vuorovaikutuksessa CPU ja memoryto ajaa ohjelman.

tuohon kuvaukseen mahtui paljon enemmän yksityiskohtia,mutta se on karkea luonnos siitä, miten konekirjoitetut hahmot suoritetaan tietokoneen suorittimilla.

ASTs analyysityökaluina

siihen mennessä,kun lähdekoodisi muutetaan bytecodeksi, on liian myöhäistä saada paljon ymmärrystä siitä, mitä kirjoitit.Bytecode on hyvin primitiveand erittäin viritetty tekemään tulkki fast.In toisin sanoen,bytecode on suunniteltu tietokoneiden yli ihmisiä.

toisaalta abstrakteissa syntaksipuissa on tarpeeksi jäsenneltyä tietoa,jotta niistä olisi hyötyä koodisi oppimisessa.Astit eivät edelleenkään ole kovin ihmisystävällisiä,mutta ne ovat järkevämpiä kuin bytecode-esitys.

koska Python on ”paristot mukana” – kieli,ASTs: n käyttöön tarvittavat työkalut on rakennettu standardikirjastoon.

ensisijainen työkalu ASTs: n kanssa työskentelyyn on ast moduuli.Katsotaanpa esimerkki nähdä, miten tämä toimii.

AST esimerkillä

alla on esimerkki Python-skriptistä, jota käytämme.Tämä skripti vastaa kysymykseen ” mitä moduuleja tuotiin?”

import astfrom pprint import pprint

def 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()

tämä koodi tekee pari merkittävää asiaa:

  1. muuttaa Python-tiedoston tekstin(tässä tapauksessa itse esimerkkikoodin)abstraktiksi syntaksipuuksi.
  2. analysoi AST: n saadakseen siitä jotain tietoa.

voit suorittaa tämän koodin:

$ python3 ast_example.py{'from': , 'import': }

muunnos AST: ksi

with open("ast_example.py", "r") as source: tree = ast.parse(source.read())

kahdella koodirivillä luetaan tiedosto ja luodaan AST,jonka nimi on treeast.parse funktio tekee tästä snap!On ton tapahtuu konepellin että toiminto, jonka voimme autuaasti sivuuttaa.

yhdellä funktiokutsulla Python käsitteli kaikki poletit,noudatti kaikkia kielen sääntöjä ja rakensi tietorakenteen (ts., puu), joka sisältää kaikki koodin suorittamiseen tarvittavat tiedot.

ennen kuin siirrytään eteenpäin, mietitään hetki, mikä puu on.Puut ovat hyvin syvä topicin ohjelmistokehitysso pidä tätä primerrather kuin tyhjentävä selitys.

puu on tapa pitää dataas joukko ”solmuja”, jotka on yhdistetty ”reunoilla.”

 +-----+ | A | +-----+ / \ / \+-----+ +-----+| B | | C |+-----+ +-----+

tässä kaaviossa A,B ja C ovat kaikki kyhmyjä, ja niissä on reunoja, jotka yhdistävät A: n B: hen ja A: n C: hen.

yksi tapa edustaa tätä puuta koodissa voisi olla:

class Node: def __init__(self, value): self.value = value self.children = tree = Node('A')tree.children.append(Node('B'))tree.children.append(Node('C'))

huomaa, että tree on itse asiassa solmu!Kun työskentelemme puu, olemme todella tekemisissä kokoelma solmuja, ja puu muuttuja on viittaus ”juuri” solmu(esim.solmu a). ottamalla tällainen rakenne,voimme tarkistaa jokaisen solmun Puun ja ryhtyä toimiin.Teemme sen käymällä jokaisen puun luona ja käsittelemällä sen tietoja.

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

nyt kun meillä on käsitys siitä,mikä puu on, voidaan pohtia, mitä esimerkkikirjoituksen seuraava osa tekee.Pythonin abstraktin syntaksipuun puurakenne liittyy enemmän sen nodien lukumäärään ja tallennettujen tietojen tyyppiin, mutta solmujen ja reunojen ydinajatus on sama.

analysoi AST

kun meillä on puu, Analyzer seuraa kävijämallia, jonka edellä osoitin tiedon saamiseksi puusta.

totesin, että Python AST on monimutkaisempi kuin minun perus Node design.Yksi ero on, että se seuraa erilaisia solmuja.Tällöin ast.NodeVisitor on hyödyllinen.

a NodeVisitor voi vastata mihin tahansa Nodein Python AST.To käy tietyntyyppisessä solmussa, on toteutettava menetelmä, joka näyttää visit_<node type>.

esimerkkikoodini yrittää selvittää tietoja imports.To oppia tuonnista, koodi vetää Import ja ImportFrom solmutyypit.

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)

tämä koodi ottaa Modulen nimen ja tallentaa sen tilastoluetteloon.Vaikka koodi ei ole fancy,se näyttää, miten vuorovaikutuksessa AST solmuja.

kun NodeVisitor Luokka on määritelty,Voimme käyttää sitä puun analysointiin.

analyzer = Analyzer()analyzer.visit(tree)

The visit method will delegate to your visit_<node type> method whenever that type of node is törmäsin samaan aikaan puun rakenteen läpi.

joten, millaisia solmutyyppejä on olemassa?Koko listan löydät ast moduulidokumentaatiosta.Totta puhuen,tuota dokumentaatiota on hieman vaikea omaksua.Sinulla voi olla enemmän menestystä viittaamalla enemmän tyhjentävä opas, kuten theGreen Tree Snakes Nodes guide.

nyt Toivottavasti ymmärrät,miten:

  1. rakentaa Ast Pythonin lähdekoodista.
  2. tee AST-analyysi käyttäen NodeVisitor.

uskon, että voit vastata moniin mielenkiintoisiin kysymyksiin koodebyistäsi käyttämällä abstrakteja syntaksipuita.Kysymykset kuten:

  • kuinka monta muuttujaa käytin?
  • mitkä ovat yleisimmät funktiokutsut koodissani?
  • ovatko moduulini tiukasti kytkettyinä toisiinsa?
  • mitkä kolmannen osapuolen kirjastot näkyvät usein eri paketeissa?

ast moduuli ei todennäköisesti ole työkalu, jolla tavoitat hyvin often.In ne ajat, joita tarvitset ast,sen minimaalinen API on melko muistettavissa ja voit analysoida koodin nopeasti.

Jos tämä olisi mielestäsi hyödyllinen,voisitko jakaa tämän Twitteriin tai lempisosiaaliselle sivustollesi?Tykkään chattailla ihmisten kanssa tällaisista topicsso vapaasti tweet me at@mblayman.

Opi Pythonista!

voit liittyä uutiskirjeeseeni yhdessä yli 1000 muun kehittäjän kanssa ja auttaa sinua oppimaan lisää Djangosta ja Pythonista.

Vastaa

Sähköpostiosoitettasi ei julkaista.