Matt Layman

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

Como é que o programa Python(melhor conhecido como o interpretador)”sabe” como executar o seu código?Se você é novo na programação, pode parecer como magic.In na verdade, ainda parece magia ser uma profissão há mais de uma década.

o interpretador de Python não é mágico(lamento desapontá-lo).segue um conjunto previsível de passos para traduzir o seu código em instruções que uma máquina pode executar.

a um nível bastante elevado,eis o que acontece ao seu código:

  1. o código é processado (ou seja, dividido) numa lista de peças normalmente chamadas fichas.Estes símbolos baseiam-se num conjunto de regras para coisas que devem ser tratadas de forma diferente.Por exemplo,a palavra-chave if é um diferente token de um valor numérico, como 42.
  2. a lista raw de tokens é transformada para construir uma árvore de sintaxe abstrata, AST, que é o assunto que vamos explorar mais neste post.Um AST é uma coleção de nodes que estão ligados entre si com base na gramática da linguagem Python.Não se preocupe se isso não fizer sentido agora, já que vamos iluminar isto em breve.
  3. a partir de uma árvore de sintaxe abstrata,o interpretador pode produzir uma forma de instrução de nível inferior chamada bytecode.Estas instruções são coisas como e são destinadas a ser muito genericso que um computador pode executá-las.com as instruções bytecode disponíveis, o interpretador pode finalmente executar o seu código.O bytecode é usado para chamar funcionalidades no seu sistema operativo que, em última análise, irão interagir com uma CPU e memorizar para executar o programa.

muitos mais detalhes poderiam caber nessa descrição, mas este é o esboço de como os caracteres tipados são executados por CPUs de computador.

ASTs como ferramentas de análise

no momento em que o seu código-fonte é transformado em bytecode,é demasiado tarde para ganhar muita compreensão sobre o que escreveu.Bytecode é muito primitivo e muito sintonizado para fazer o interpretador fast.In outras palavras, bytecode é projetado para computadores sobre pessoas.

Por outro lado, as árvores de sintaxe abstrata têm informações estruturadas suficientes nelas para torná-las úteis para aprender sobre o seu código.ASTs ainda não são muito amigáveis com as pessoas,mas eles são mais sensíveis do que a representação bytecode.

porque Python é uma linguagem de “baterias incluídas”, as ferramentas que você precisa para usar ASTs são construídas na biblioteca padrão.

a ferramenta primária para trabalhar com o ASTs é o módulo ast.Vejamos um exemplo para ver como isso funciona.

ast por exemplo

abaixo está o exemplo Python script que vamos usar.Este script responde à questão de ” quais módulos foram importados?”

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

Este código faz algumas coisas importantes:

  1. Transforma um Python arquivo de texto(neste caso, o exemplo de código em si)em uma árvore de sintaxe abstrata.
  2. analisa o AST para extrair alguma informação dele.

pode executar este código como:

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

Transformar a AST

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

Em duas linhas de código,podemos ler um arquivo e criar uma AST chamado tree.A função ast.parse faz disto um snap!Há uma tonelada a acontecer debaixo do capô dessa função que podemos alegremente ignorar.

com uma chamada de função,Python processou todos os tokens, seguiu todas as regras da linguagem ,e construiu uma estrutura de dados (i.e., uma árvore) contendo todas as informações relevantes para executar o código.antes de seguir em frente,vamos pensar no que é uma árvore.As árvores são um desenvolvimentode software de topicina muito profundo, pelo que consideramque se trata de uma explicação primitiva e não de uma explicação exaustiva.

uma árvore é uma forma de manter dados como um conjunto de “nós” conectados por “bordas”.”

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

neste diagrama,A, B, e C são todos nodesand existem arestas conectando a para B e de a para C.

Uma maneira de representar esta árvore de código pode ser:

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

Aviso de que o tree é, na verdade, um nó!Quando trabalhamos com uma árvore,estamos realmente a lidar com uma colecção de nós,e a variável árvore é uma referência ao nó “raiz” (por exemplo, nó A).Ao Termos este tipo de estrutura,podemos verificar cada nó na árvore e agir.Fazemo-lo visitando cada um node no Tratado e processando os seus dados.

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

Agora que temos uma idéia do que uma árvore seja,podemos considerar que a próxima sectionof o exemplo de script faz.A estrutura da árvore da sintaxe abstrata Python é mais envolvida devido à contagem de seus nodes e o tipo de dados armazenados,ainda que a idéia central de nós e arestas é a mesma.

analisa o AST

Uma vez que temos a árvore,o Analyzer segue o padrão de visitantes que eu mostrei a informação extraída acima da árvore.

I observed that a Python AST is more complex than my basic Node design.Uma diferença é que ele rastreia vários tipos de nós.Isto é onde ast.NodeVisitor é útil.

aNodeVisitor pode responder a qualquer tipo de nodein no Python AST.To visite um tipo particular de nó,devemos implementar um método que se pareça com visit_<node type>.

O meu código de exemplo está a tentar descobrir imports.To aprenda sobre as importações, o código puxa do Import e ImportFrom tipos de nó.

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)

Este código leva o nome do moduleand lojas itin uma lista das estatísticas.Embora o código não seja chique,ele mostra como interagir com os nós AST.

com a classe definida de NodeVisitor, podemos usá-la para analisar a árvore.

analyzer = Analyzer()analyzer.visit(tree)

visit método delegará a sua visit_<node type> methodwhenever que tipo de nó é encounteredwhile percorrer através da estrutura de árvore.

então, que tipos de nó existem?Você pode encontrar a lista completa na seção gramatical deabstract doast documentação do módulo.Na verdade, acho essa documentação um pouco difícil de absorver.Você pode ter mais sucesso, referindo-se a um guia mais exaustivo como o Guia Green Tree Snakes Nodes guide.

encerrando

por esta altura,espera-se que compreenda como:

  1. construir um AST a partir do código-fonte Python.
  2. do analysis on the AST using a NodeVisitor.

acho que pode responder a muitas perguntas interessantes sobre o seu código usando árvores de sintaxe abstratas.Perguntas como:

  • quantas variáveis usei?
  • Quais são as chamadas de função mais comuns no meu código?os meus módulos estão estreitamente ligados um ao outro?que bibliotecas de terceiros aparecem frequentemente em pacotes diferentes?

oast módulo provavelmente não é uma ferramenta que você irá alcançar para muito often.In as vezes que você precisa de ast,sua API mínima é bastante memorável e você pode analisar o código rapidamente.se achar isto útil, importa-se de partilhar isto no Twitteror ou no seu site de redes sociais favorito?Eu gosto de conversar com pessoas sobre este tipo de topicsso sinta-se livre para twittar-me no@mblayman.

Aprenda sobre Python!

pode juntar-se à minha newsletter juntamente com mais de 1000 programadores para o ajudar a aprender mais sobre o Django e o Python.

Deixe uma resposta

O seu endereço de email não será publicado.