This document is for an old version of Python that is no longer supported. You should upgrade and read the documentação do Python para versão estável atual.

# 32.2. `ast` — Árvores de Sintaxe Abstrata

Novo na versão 2.5: The low-level `_ast` module containing only the node classes.

Novo na versão 2.6: The high-level `ast` module containing all helpers.

Código-fonte: Lib/ast.py

O módulo `ast` ajuda os aplicativos Python a processar árvores da gramática de sintaxe abstrata do Python. A sintaxe abstrata em si pode mudar em cada lançamento do Python; este módulo ajuda a descobrir programaticamente como é a gramática atual.

Uma árvore de sintaxe abstrata pode ser gerada passando `ast.PyCF_ONLY_AST` como um sinalizador para a função interna `compile()`, ou usando o auxiliar `parse()` fornecido neste módulo. O resultado será uma árvore de objetos cujas classes herdam de `ast.AST`. Uma árvore de sintaxe abstrata pode ser compilada em um objeto de código Python usando a função interna `compile()`.

## 32.2.1. Classes de nó

class `ast.``AST`

  Esta é a base de todas as classes de nós AST. As classes de nós reais são derivadas do arquivo `Parser/Python.asdl`, o qual é reproduzido abaixo. Elas são definidas no módulo C `_ast` e reexportadas em `ast`.

  Há uma classe definida para cada símbolo do lado esquerdo na gramática abstrata (por exemplo, `ast.stmt` ou `ast.expr`). Além disso, existe uma classe definida para cada construtor no lado direito; essas classes herdam das classes para as árvores do lado esquerdo. Por exemplo, `ast.BinOp` herda de `ast.expr`. Para regras de produção com alternativas (“somas”), a classe do lado esquerdo é abstrata: apenas instâncias de nós construtores específicos são criadas.

  `_fields`

    Cada classe concreta possui um atributo `_fields` que fornece os nomes de todos os nós filhos.

    Cada instância de uma classe concreta tem um atributo para cada nó filho, do tipo definido na gramática. Por exemplo, as instâncias `ast.BinOp` possuem um atributo `left` do tipo `ast.expr`.

    Se estes atributos estiverem marcados como opcionais na gramática (usando um ponto de interrogação), o valor pode ser `None`. Se os atributos puderem ter valor zero ou mais (marcados com um asterisco), os valores serão representados como listas do Python. Todos os atributos possíveis devem estar presentes e ter valores válidos ao compilar uma AST com `compile()`.

  `lineno`
  `col_offset`

    Instances of `ast.expr` and `ast.stmt` subclasses have `lineno` and `col_offset` attributes. The `lineno` is the line number of source text (1-indexed so the first line is line 1) and the `col_offset` is the UTF-8 byte offset of the first token that generated the node. The UTF-8 offset is recorded because the parser uses UTF-8 internally.

  O construtor de uma classe `ast.T` analisa seus argumentos da seguinte forma:

  - Se houver argumentos posicionais, deve haver tantos quanto houver itens em `T._fields`; eles serão atribuídos como atributos desses nomes.

  - Se houver argumentos de palavra-chave, eles definirão os atributos dos mesmos nomes para os valores fornecidos.

  Por exemplo, para criar e popular um nó `ast.UnaryOp`, você poderia usar

      node = ast.UnaryOp()
      node.op = ast.USub()
      node.operand = ast.Num()
      node.operand.n = 5
      node.operand.lineno = 0
      node.operand.col_offset = 0
      node.lineno = 0
      node.col_offset = 0

  ou a forma mais compacta

      node = ast.UnaryOp(ast.USub(), ast.Num(5, lineno=0, col_offset=0),
                         lineno=0, col_offset=0)

  Novo na versão 2.6: The constructor as explained above was added. In Python 2.5 nodes had to be created by calling the class constructor without arguments and setting the attributes afterwards.

## 32.2.2. Gramática Abstrata

The module defines a string constant `__version__` which is the decimal Subversion revision number of the file shown below.

A gramática abstrata está atualmente definida da seguinte forma:

    -- ASDL's five builtin types are identifier, int, string, object, bool

    module Python version "$Revision$"
    {
    	mod = Module(stmt* body)
    	    | Interactive(stmt* body)
    	    | Expression(expr body)

    	    -- not really an actual node but useful in Jython's typesystem.
    	    | Suite(stmt* body)

    	stmt = FunctionDef(identifier name, arguments args,
                                stmt* body, expr* decorator_list)
    	      | ClassDef(identifier name, expr* bases, stmt* body, expr* decorator_list)
    	      | Return(expr? value)

    	      | Delete(expr* targets)
    	      | Assign(expr* targets, expr value)
    	      | AugAssign(expr target, operator op, expr value)

    	      -- not sure if bool is allowed, can always use int
     	      | Print(expr? dest, expr* values, bool nl)

    	      -- use 'orelse' because else is a keyword in target languages
    	      | For(expr target, expr iter, stmt* body, stmt* orelse)
    	      | While(expr test, stmt* body, stmt* orelse)
    	      | If(expr test, stmt* body, stmt* orelse)
    	      | With(expr context_expr, expr? optional_vars, stmt* body)

    	      -- 'type' is a bad name
    	      | Raise(expr? type, expr? inst, expr? tback)
    	      | TryExcept(stmt* body, excepthandler* handlers, stmt* orelse)
    	      | TryFinally(stmt* body, stmt* finalbody)
    	      | Assert(expr test, expr? msg)

    	      | Import(alias* names)
    	      | ImportFrom(identifier? module, alias* names, int? level)

    	      -- Doesn't capture requirement that locals must be
    	      -- defined if globals is
    	      -- still supports use as a function!
    	      | Exec(expr body, expr? globals, expr? locals)

    	      | Global(identifier* names)
    	      | Expr(expr value)
    	      | Pass | Break | Continue

    	      -- XXX Jython will be different
    	      -- col_offset is the byte offset in the utf8 string the parser uses
    	      attributes (int lineno, int col_offset)

    	      -- BoolOp() can use left & right?
    	expr = BoolOp(boolop op, expr* values)
    	     | BinOp(expr left, operator op, expr right)
    	     | UnaryOp(unaryop op, expr operand)
    	     | Lambda(arguments args, expr body)
    	     | IfExp(expr test, expr body, expr orelse)
    	     | Dict(expr* keys, expr* values)
    	     | Set(expr* elts)
    	     | ListComp(expr elt, comprehension* generators)
    	     | SetComp(expr elt, comprehension* generators)
    	     | DictComp(expr key, expr value, comprehension* generators)
    	     | GeneratorExp(expr elt, comprehension* generators)
    	     -- the grammar constrains where yield expressions can occur
    	     | Yield(expr? value)
    	     -- need sequences for compare to distinguish between
    	     -- x < 4 < 3 and (x < 4) < 3
    	     | Compare(expr left, cmpop* ops, expr* comparators)
    	     | Call(expr func, expr* args, keyword* keywords,
    			 expr? starargs, expr? kwargs)
    	     | Repr(expr value)
    	     | Num(object n) -- a number as a PyObject.
    	     | Str(string s) -- need to specify raw, unicode, etc?
    	     -- other literals? bools?

    	     -- the following expression can appear in assignment context
    	     | Attribute(expr value, identifier attr, expr_context ctx)
    	     | Subscript(expr value, slice slice, expr_context ctx)
    	     | Name(identifier id, expr_context ctx)
    	     | List(expr* elts, expr_context ctx)
    	     | Tuple(expr* elts, expr_context ctx)

    	      -- col_offset is the byte offset in the utf8 string the parser uses
    	      attributes (int lineno, int col_offset)

    	expr_context = Load | Store | Del | AugLoad | AugStore | Param

    	slice = Ellipsis | Slice(expr? lower, expr? upper, expr? step)
    	      | ExtSlice(slice* dims)
    	      | Index(expr value)

    	boolop = And | Or

    	operator = Add | Sub | Mult | Div | Mod | Pow | LShift
                     | RShift | BitOr | BitXor | BitAnd | FloorDiv

    	unaryop = Invert | Not | UAdd | USub

    	cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn

    	comprehension = (expr target, expr iter, expr* ifs)

    	-- not sure what to call the first argument for raise and except
    	excepthandler = ExceptHandler(expr? type, expr? name, stmt* body)
    	                attributes (int lineno, int col_offset)

    	arguments = (expr* args, identifier? vararg,
    		     identifier? kwarg, expr* defaults)

            -- keyword arguments supplied to call
            keyword = (identifier arg, expr value)

            -- import name with optional 'as' alias.
            alias = (identifier name, identifier? asname)
    }

## 32.2.3. Auxiliares de `ast`

Novo na versão 2.6.

Apart from the node classes, `ast` module defines these utility functions and classes for traversing abstract syntax trees:

`ast.``parse`(source, filename='<unknown>', mode='exec')

  Analisa a fonte em um nó AST. Equivalente a `compile(source, filename, mode, ast.PyCF_ONLY_AST)`.

  Aviso

  É possível travar o interpretador Python com uma string suficientemente grande/complexa devido às limitações de profundidade da pilha no compilador de AST do Python.

`ast.``literal_eval`(node_or_string)

  Safely evaluate an expression node or a Unicode or Latin-1 encoded string containing a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and `None`.

  Isso pode ser usado para avaliar com segurança strings contendo valores Python de fontes não confiáveis sem a necessidade de analisar os valores por si próprio. Não é capaz de avaliar expressões arbitrariamente complexas, por exemplo, envolvendo operadores ou indexação.

  Aviso

  É possível travar o interpretador Python com uma string suficientemente grande/complexa devido às limitações de profundidade da pilha no compilador de AST do Python.

`ast.``get_docstring`(node, clean=True)

  Return the docstring of the given node (which must be a `FunctionDef`, `ClassDef` or `Module` node), or `None` if it has no docstring. If clean is true, clean up the docstring’s indentation with `inspect.cleandoc()`.

`ast.``fix_missing_locations`(node)

  Quando você compila uma árvore de nós com `compile()`, o compilador espera atributos `lineno` e `col_offset` para cada nó que os suporta. Isso é tedioso para preencher nós gerados, portanto, esse auxiliar adiciona esses atributos recursivamente, onde ainda não estão definidos, definindo-os para os valores do nó pai. Ele funciona recursivamente a partir do node.

`ast.``increment_lineno`(node, n=1)

  Increment the line number of each node in the tree starting at node by n. This is useful to “move code” to a different location in a file.

`ast.``copy_location`(new_node, old_node)

  Copy source location (`lineno` and `col_offset`) from old_node to new_node if possible, and return new_node.

`ast.``iter_fields`(node)

  Produz uma tupla de `(fieldname, value)` para cada campo em `node._fields` que esteja presente em node.

`ast.``iter_child_nodes`(node)

  Produz todos os nós filhos diretos de node, ou seja, todos os campos que são nós e todos os itens de campos que são listas de nós.

`ast.``walk`(node)

  Produz recursivamente todos os nós descendentes na árvore começando em node (incluindo o próprio node), em nenhuma ordem especificada. Isso é útil se você quiser apenas modificar nós no lugar e não se importar com o contexto.

class `ast.``NodeVisitor`

  Uma classe base de visitante de nó que percorre a árvore de sintaxe abstrata e chama uma função de visitante para cada nó encontrado. Esta função pode retornar um valor que é encaminhado pelo método `visit()`.

  Esta classe deve ser uma subclasse, com a subclasse adicionando métodos visitantes.

  `visit`(node)

    Visita um nó. A implementação padrão chama o método chamado `self.visit_nomedaclasse` sendo nomedaclasse o nome da classe do nó, ou `generic_visit()` se aquele método não existir.

  `generic_visit`(node)

    Este visitante chama `visit()` em todos os filhos do nó.

    Observe que nós filhos de nós que possuem um método de visitante personalizado não serão visitados, a menos que o visitante chame `generic_visit()` ou os visite por conta própria.

  Não use o `NodeVisitor` se você quiser aplicar mudanças nos nós durante a travessia. Para isso existe um visitante especial (`NodeTransformer`) que permite modificações.

class `ast.``NodeTransformer`

  A subclasse `NodeVisitor` que percorre a árvore de sintaxe abstrata e permite a modificação de nós.

  O `NodeTransformer` percorrerá a AST e usará o valor de retorno dos métodos do visitante para substituir ou remover o nó antigo. Se o valor de retorno do método visitante for `None`, o nó será removido de seu local, caso contrário, ele será substituído pelo valor de retorno. O valor de retorno pode ser o nó original, caso em que não há substituição.

  Aqui está um exemplo de transformador que rescreve todas as ocorrências de procuras por nome (`foo`) para `data['foo']`:

      class RewriteName(NodeTransformer):

          def visit_Name(self, node):
              return copy_location(Subscript(
                  value=Name(id='data', ctx=Load()),
                  slice=Index(value=Str(s=node.id)),
                  ctx=node.ctx
              ), node)

  Tenha em mente que, se o nó em que você está operando tiver nós filhos, você deve transformar os nós filhos por conta própria ou chamar o método `generic_visit()` para o nó primeiro.

  Para nós que faziam parte de uma coleção de instruções (que se aplica a todos os nós de instrução), o visitante também pode retornar uma lista de nós em vez de apenas um único nó.

  Normalmente você usa o transformador assim:

      node = YourTransformer().visit(node)

`ast.``dump`(node, annotate_fields=True, include_attributes=False)

  Return a formatted dump of the tree in node. This is mainly useful for debugging purposes. The returned string will show the names and the values for fields. This makes the code impossible to evaluate, so if evaluation is wanted annotate_fields must be set to `False`. Attributes such as line numbers and column offsets are not dumped by default. If this is wanted, include_attributes can be set to `True`.