PythonのAST(Python抽象構文木)の解析結果を分かり易く可視化するコードの試作


#   はじめに

Pythonのコードを解析するツール(Python標準ライブラリにあるAST)を使用して、Pythonのコード(構文構造)を解析した結果の内容を、Pythonの元コードと合わせて分かり易くまとめてテキスト形式で出力します。

##   AST

Pythonのコードを解析して、構文に分解、結果をツリー状の辞書(dict)として得られる、AST(Python抽象構文木)が、Python標準ライブラリの中にあります。

https://qiita.com/rhoboro/items/5bbaa3fa659ed7454d56

https://docs.python.org/ja/3/library/ast.html

ASTコード解析結果の辞書(dict)は、例えば下記の図のようなものになります。

ASTコード解析結果例:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606924/bb6aa649-fa6a-cb85-04b3-9bd1edd1f6ca.png)

辞書(dict)の形式では、全情報が羅列され、構造が見えにくく、元のコードとの対応も分かりにくいものになります。

##   結果を分かり易くまとめて出力

このASTコード解析結果の辞書(dict)形式のままでは、結果が見にくいので、下図のように**Pythonの元コードと併記して構造を可視化し、分かり易くまとめてテキスト形式で出力**するコードを、ここで試作します。

試作コードの出力結果例: (下図)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606924/1cdf4021-8992-9838-4fb9-388426b2e9a4.png)


#   使用方法 (呼出し方法)

試作したコードは、後述の「コード全体」章にあります。

この試作コードを用いて、ASTコード解析結果を分かり易くまとめて出力するには、
```py
print_ast("sample_code.py")
```
上記のように、print_ast関数を呼び出すのみになります。

引数に解析したいPythonコードのファイル(.py)へのパスを指定します。
実行すると、ASTコード解析結果を分かり易くまとめたテキスト形式のファイルが出力されます。

#   処理方法

大きく3つの部分からなり、
* class AstResultPrinter
* class AstAndPyCodeZipper
* def print_ast

それぞれ、
* 実体のメインは、AstResultPrinterクラス、
* AstAndPyCodeZipperクラスは、ASTコード解析結果を、Pythonの元コードと併記した形で出力するもの、
* print_ast関数は、AstResultPrinterクラスを簡単に呼び出せるようにした関数(ヘルパー関数)、

になります。

ASTコード解析結果から得られる各要素のNodeオブジェクトを、辞書(dict)形式の文字列に直して(`str(node_i.__dict__)`)、表示が不要なものを除去するテキスト置換を繰り返し行う処理がメインになります。

これに合わせて、各要素のNodeオブジェクトに対応する、Pythonの元コードを抽出し(`class AstAndPyCodeZipper`)、ASTコード解析結果と元コードを併記して分かり易くまとめてテキスト形式で出力します。

#   コードの構成

試作したコード全体の構成は、

```:コードの構成
import:
-------
グローバル域でimport:
import ast, re
import pathlib

ローカル域でimport:
なし

コード構造:
-----------

# sec: main

def main(): # 実行切替用

def run__main1():
      ↓
    # sec: config
      ↓
    # sec: run

# sec: AST(Python抽象構文木)可視化

# ASTコード解析結果を分かり易くまとめてテキスト形式で出力、Pythonの元コードと合わせて併記
class AstResultPrinter:

    def print_ast(cls, 

        (内包関数)
        def print_node(node, lv=0):
              ↓
            # sec: 対応するpyコードを取得
              ↓
            # sec: 位置
              ↓
            # sec: 読込型・書込型
              ↓
            # sec: 置換 (表示が不要なものを除去)
              ↓
            # sec: 出力

# ASTのnodeが指し示す行位置に対応するpyコードを返す
class AstAndPyCodeZipper:

    def __init__(self, code):
          ↓
        # sec: config
          ↓
        # sec: inner state

            (内包関数)
            def get_next_py_code__non(self, *args, **kwargs): return ""

    # ASTのnodeが指し示す行位置に対応するpyコードを取得 (前回の書出し分は除く)
    def get_next_py_code(self, node, i_from=None, i_to=None):
          ↓
        # sec: pyコード
          ↓
        # sec: 整形

    # ASTのnodeが指し示す行位置に対応するpyコードを取得 (前回の書出し分は除く)
    def get_next_py_code__raw(self, node, i_from=None, i_to=None):
          ↓
        # sec: nodeの行位置
          ↓
        # sec: 対応するpyコード

# ASTコード解析結果を分かり易くまとめてテキスト形式で出力、Pythonの元コードと合わせて併記
def print_ast(
      ↓
    # sec: 引数チェック
      ↓
    # sec: main
          ↓
        # sec: AST解析
          ↓
        # sec: AST可視化
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606924/03bb3dab-cab0-422e-b047-ec651e2ab5bf.png)

#   コード全体

試作したコード全体は、

```py:run__print_AST.py
# -*- coding: utf-8 -*-

# AST(pyコード分析ツリー)内容を可視化する機能
# ASTコード解析結果を分かり易くまとめてテキスト形式で出力、Pythonの元コードと合わせて併記

import ast, re
import pathlib

# sec: main

def main(): # 実行切替用
    run__main1()

def run__main1():

    # sec: config
    
    path_py = "sample_code1.py"
    # path_py = "sample_code2__run__car_path_plan_simu.py"
    
    # sec: run
    
    print_ast(path_py)
    
# sec: AST(pyコード分析ツリー)可視化

# ASTコード解析結果を分かり易くまとめてテキスト形式で出力、Pythonの元コードと合わせて併記
class AstResultPrinter:

    re_key = re.compile(r"'(?P<n>[\d\w]+)':") # key名マッチ
    re_line_B = re.compile(r"lineno\: \d+[,}]\s*") # 行情報マッチ
    re_col_B = re.compile(r"col_offset\: \d+[,}]\s*") # 文字位置情報マッチ
    re_line_E = re.compile(r"end_lineno\: \d+[,}]\s*") # 行情報マッチ
    re_col_E = re.compile(r"end_col_offset\: \d+[,}]\s*") # 文字位置情報マッチ
    re_obj = re.compile(r"\<_?ast\.(?P<c>\w+) object at 0x[\d\w]+\>") # ASTクラス表記マッチ
    re_end1 = re.compile(r",\s*$") # 余分な末尾","マッチ
    re_end2 = re.compile(r"(?<=[^}])$") # "}"なしの末尾マッチ
    
    @classmethod
    def print_ast(cls, 
        node, # ASTコード解析結果のツリーオブジェクト(ast.parse(code)の結果を渡す)
        code = None, # pyソースコードのテキスト
        path_out = "print_ast.py"): # 出力ファイルへのパス
        
        pyco = AstAndPyCodeZipper(code) # 対応するpyコードを取得
        pyco.header = ">" + "=" * 60 + ":py\n"
        pyco.prefix = "{0:4d}|py: "
        pyco.footer = " " + "- " * 30 + ":ast\n"
        
        file = open(path_out, "w")
        
        def print_node(node, lv=0):
            
            for node_i in ast.iter_child_nodes(node): # 全てflat化して子node列挙
            
                if node_i.__class__.__name__ in ("Load", "Store"): # if: 内容無しクラス -> 飛ばす
                    continue
                
                # sec: 対応するpyコードを取得
                
                code_py = pyco.get_next_py_code(node_i) # NOTE: 後段でpyco.has_posを使う為、get_next_py_codeはそれ以前に呼出し
                if len(code_py) > 0:
                    file.write(code_py)
                
                # sec: 位置
                
                try:
                    i_line, i_col, has_pos = node_i.lineno - 1, node_i.col_offset - 1, True # 開始番号は1からの為
                except:
                    has_pos = False
                
                if has_pos:
                    text_no = "%4d:%2d|" % (i_line + 1, i_col + 1)
                else:
                    text_no = "       |"
                
                # sec: 読込型・書込型
                
                try:
                    text_ctx = node_i.ctx.__class__.__name__
                except:
                    text_ctx = ""
                if text_ctx == "Load": # if: 変数から読込型
                    text_rw = "R "
                elif text_ctx == "Store": # if: 変数へ書込型
                    text_rw = "W "
                else:
                    text_rw = "  "
                
                # sec: 置換 (表示が不要なものを除去)
                
                text_di = str(node_i.__dict__) # nodeのメンバ dictの文字列表記
                text_di = cls.re_key.sub(r"\g<n>:", text_di)
                text_di = cls.re_line_E.sub("", text_di) # 同じ文字列を含む為、re_line_Eから除去
                text_di = cls.re_col_E.sub("", text_di)
                text_di = cls.re_line_B.sub("", text_di) # 同じ文字列を含む為、後でre_line_Bを除去
                text_di = cls.re_col_B.sub("", text_di)
                text_di = cls.re_obj.sub(r"\g<c>", text_di)
                text_di = text_di.replace("ctx: Load, ", "")
                text_di = text_di.replace(", ctx: Load", "")
                text_di = text_di.replace("ctx: Store, ", "")
                text_di = text_di.replace(", ctx: Store", "")
                text_di = text_di.replace(", type_comment: None", "") # 変数の属性 型なし時は除去
                text_di = text_di.replace(", kind: None", "") # Constantの属性 種なし時は除去
                text_di = text_di.replace("posonlyargs: [], ", "") # argumentsの属性 空時は除去
                text_di = cls.re_end1.sub("", text_di)
                text_di = cls.re_end2.sub("}", text_di)
                
                # sec: 出力
                
                file.write("%s%s %s %s %s\n" % (text_no, text_rw, " " * lv * 4, node_i.__class__.__name__, text_di))
                
                print_node(node_i, lv + 1) # 再帰呼び出し
        
        print_node(node, lv=0)
        
        file.close()

# ASTのnodeが指し示す行位置に対応するpyコードを返す
class AstAndPyCodeZipper:
    # assume: コード上方から順番に処理され、get_next_py_codeが順次呼び出される想定
    
    def __init__(self, code):
        
        # sec: config
        
        self.header = ">" + "=" * 60 + ":py\n"
        self.prefix = "{0:4d}|py: " # {0:4d}等でpy行番号が入る
        self.footer = " " + "- " * 30 + ":ast\n"
        
        # sec: inner state
        
        if code is None: # if: 機能無効化
            def get_next_py_code__non(self, *args, **kwargs): return ""
            self.get_next_py_code = get_next_py_code__non
            return
        
        self.codes = code.split("\n")
        self.i_E_curr = -1
    
    # ASTのnodeが指し示す行位置に対応するpyコードを取得 (前回の書出し分は除く)
    def get_next_py_code(self, node, i_from=None, i_to=None):
        
        # sec: pyコード
        
        codes_py = self.get_next_py_code__raw(node, i_from, i_to)
        if len(codes_py) == 0: # if: pyコード無し
            return ""
        
        i_B_code = self.i_E_curr - len(codes_py) + 1 # pyコード先頭行番号
        
        # sec: 整形
        
        text_out = self.header
        
        for i_line, code_py in enumerate(codes_py):
            text_out += self.prefix.format(i_B_code + i_line + 1) + code_py + "\n"
        
        text_out += self.footer
        
        return text_out
    
    # ASTのnodeが指し示す行位置に対応するpyコードを取得 (前回の書出し分は除く)
    def get_next_py_code__raw(self, node, i_from=None, i_to=None):
        # assume: 後段処理の都合上、切り出し結果は行のリストで返す
        
        # sec: nodeの行位置
        
        try:
            i_line, has_pos = node.lineno - 1, True # 開始番号は1からの為
        except:
            i_line, has_pos = -1, False
        
        # sec: 対応するpyコード
        
        codes_py = []
        if has_pos and i_line > self.i_E_curr: # if: 未書出し行有り
            
            if i_from is None:
                i_B = self.i_E_curr + 1
            else:
                i_B = i_from
            if i_to is None:
                i_E = i_line
            else:
                i_E = i_to
            
            codes_py = self.codes[i_B:i_E + 1] # 未書出し行の部分を切り出し
            
            self.i_E_curr = i_E
            
        return codes_py
    
# ASTコード解析結果を分かり易くまとめてテキスト形式で出力、Pythonの元コードと合わせて併記
def print_ast(
    path_in = None, # pyソースコードのパス ※下記node＆code or path_inの一方を指定
    node = None, code = None, # AST解析結果のツリーオブジェクト、pyソースコードのテキスト
    path_out = None): # 出力ファイルへのパス
    
    # sec: 引数チェック
    
    if pathlib.Path(str(node)).exists(): # if: 第1引数が有効なパス
        path_in = str(node)
        node = None # nodeは無効に
    
    if path_out is None: # if: 出力パスの指定なし
        if path_in is None:
            path_out = "print_ast.py"
        else:
            path_out = pathlib.Path(path_in).stem + ".print_ast.py" # 自動で命名
    
    # sec: main
    
    if node is not None:

        # sec: AST可視化
            
        AstResultPrinter.print_ast(node, code, path_out)
    
    elif path_in is not None:
        
        # sec: AST解析
        
        with open(path_in) as file:
            code = file.read()
        
        node = ast.parse(code)
        
        # sec: AST可視化
            
        AstResultPrinter.print_ast(node, code, path_out)


# sec: entry

if __name__ == "__main__": main()
```

#   出力結果例

前述の試作したコードを実行して得られる出力結果(Pythonの元コードと併記して構造を可視化し、分かり易くまとめてテキスト形式で出力したもの)は、例えば、

```:出力結果
>============================================================:py
   1|py: # -*- coding: utf-8 -*-
   2|py: 
   3|py: import numpy
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
   3: 0|    Import {names: [alias]}
       |        alias {name: 'numpy', asname: None}
>============================================================:py
   4|py: import numpy as np
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
   4: 0|    Import {names: [alias]}
       |        alias {name: 'numpy', asname: 'np'}
>============================================================:py
   5|py: from numpy import random, a, b, c
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
   5: 0|    ImportFrom {module: 'numpy', names: [alias, alias, alias, alias], level: 0}
       |        alias {name: 'random', asname: None}
       |        alias {name: 'a', asname: None}
       |        alias {name: 'b', asname: None}
       |        alias {name: 'c', asname: None}
>============================================================:py
   6|py: from numpy import *
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
   6: 0|    ImportFrom {module: 'numpy', names: [alias], level: 0}
       |        alias {name: '*', asname: None}
>============================================================:py
   7|py: import scipy
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
   7: 0|    Import {names: [alias]}
       |        alias {name: 'scipy', asname: None}
>============================================================:py
   8|py: import matplotlib.pyplot as plt
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
   8: 0|    Import {names: [alias]}
       |        alias {name: 'matplotlib.pyplot', asname: 'plt'}
>============================================================:py
   9|py: 
  10|py: # sec: main
  11|py: 
  12|py: def main():
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  12: 0|    FunctionDef {name: 'main', args: arguments, body: [Assign, Assign, Assign, Assign, Expr, Assign, Assign, Assign, Assign, Assign, Assign, Assign, Assign, Assign, Assign, Assign, Assign, Assign, Assign, Assign, AugAssign, AugAssign, Assign, AugAssign, If, Assign, Assign, For, For, For, While, Return, FunctionDef, Expr, ClassDef, Assign], decorator_list: [], returns: None}
       |        arguments {args: [], vararg: None, kwonlyargs: [], kw_defaults: [], kwarg: None, defaults: []}
>============================================================:py
  13|py: 
  14|py:     # ●式
  15|py:     
  16|py:     d = Data() # データ格納オブジェクト
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  16: 4|        Assign {targets: [Name], value: Call}
  16: 4|W           Name {id: 'd'}
  16: 8|            Call {func: Name, args: [], keywords: []}
  16: 8|R               Name {id: 'Data'}
>============================================================:py
  17|py:     d.x = Data(0xABC)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  17: 4|        Assign {targets: [Attribute], value: Call}
  17: 4|W           Attribute {value: Name, attr: 'x'}
  17: 4|R               Name {id: 'd'}
  17:10|            Call {func: Name, args: [Constant], keywords: []}
  17:10|R               Name {id: 'Data'}
  17:15|                Constant {value: 2748}
>============================================================:py
  18|py:     d.x.y = Data(0b1010_1111, numpy.a)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  18: 4|        Assign {targets: [Attribute], value: Call}
  18: 4|W           Attribute {value: Attribute, attr: 'y'}
  18: 4|R               Attribute {value: Name, attr: 'x'}
  18: 4|R                   Name {id: 'd'}
  18:12|            Call {func: Name, args: [Constant, Attribute], keywords: []}
  18:12|R               Name {id: 'Data'}
  18:17|                Constant {value: 175}
  18:30|R               Attribute {value: Name, attr: 'a'}
  18:30|R                   Name {id: 'numpy'}
>============================================================:py
  19|py:     d.x.y.z = 0
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  19: 4|        Assign {targets: [Attribute], value: Constant}
  19: 4|W           Attribute {value: Attribute, attr: 'z'}
  19: 4|R               Attribute {value: Attribute, attr: 'y'}
  19: 4|R                   Attribute {value: Name, attr: 'x'}
  19: 4|R                       Name {id: 'd'}
  19:14|            Constant {value: 0}
>============================================================:py
  20|py:     
  21|py:     func_A(d, 0)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  21: 4|        Expr {value: Call}
  21: 4|            Call {func: Name, args: [Name, Constant], keywords: []}
  21: 4|R               Name {id: 'func_A'}
  21:11|R               Name {id: 'd'}
  21:14|                Constant {value: 0}
>============================================================:py
  22|py:     y = func_A(d, 0)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  22: 4|        Assign {targets: [Name], value: Call}
  22: 4|W           Name {id: 'y'}
  22: 8|            Call {func: Name, args: [Name, Constant], keywords: []}
  22: 8|R               Name {id: 'func_A'}
  22:15|R               Name {id: 'd'}
  22:18|                Constant {value: 0}
>============================================================:py
  23|py:     f = lambda x: x**2
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  23: 4|        Assign {targets: [Name], value: Lambda}
  23: 4|W           Name {id: 'f'}
  23: 8|            Lambda {args: arguments, body: BinOp}
       |                arguments {args: [arg], vararg: None, kwonlyargs: [], kw_defaults: [], kwarg: None, defaults: []}
  23:15|                    arg {arg: 'x', annotation: None}
  23:18|                BinOp {left: Name, op: Pow, right: Constant}
  23:18|R                   Name {id: 'x'}
       |                    Pow {}
  23:21|                    Constant {value: 2}
>============================================================:py
  24|py: 
  25|py:     a = numpy.a.b.c.arange(0, 1, 0.1, dtype=numpy.float) # 名前空間参照
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  25: 4|        Assign {targets: [Name], value: Call}
  25: 4|W           Name {id: 'a'}
  25: 8|            Call {func: Attribute, args: [Constant, Constant, Constant], keywords: [keyword]}
  25: 8|R               Attribute {value: Attribute, attr: 'arange'}
  25: 8|R                   Attribute {value: Attribute, attr: 'c'}
  25: 8|R                       Attribute {value: Attribute, attr: 'b'}
  25: 8|R                           Attribute {value: Name, attr: 'a'}
  25: 8|R                               Name {id: 'numpy'}
  25:27|                Constant {value: 0}
  25:30|                Constant {value: 1}
  25:33|                Constant {value: 0.1}
  25:38|                keyword {arg: 'dtype', value: Attribute}
  25:44|R                   Attribute {value: Name, attr: 'float'}
  25:44|R                       Name {id: 'numpy'}
>============================================================:py
  26|py:     a[0], a[1+2*3**4] = 10, 11
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  26: 4|        Assign {targets: [Tuple], value: Tuple}
  26: 4|W           Tuple {elts: [Subscript, Subscript]}
  26: 4|W               Subscript {value: Name, slice: Constant}
  26: 4|R                   Name {id: 'a'}
  26: 6|                    Constant {value: 0}
  26:10|W               Subscript {value: Name, slice: BinOp}
  26:10|R                   Name {id: 'a'}
  26:12|                    BinOp {left: Constant, op: Add, right: BinOp}
  26:12|                        Constant {value: 1}
       |                        Add {}
  26:14|                        BinOp {left: Constant, op: Mult, right: BinOp}
  26:14|                            Constant {value: 2}
       |                            Mult {}
  26:16|                            BinOp {left: Constant, op: Pow, right: Constant}
  26:16|                                Constant {value: 3}
       |                                Pow {}
  26:19|                                Constant {value: 4}
  26:24|R           Tuple {elts: [Constant, Constant]}
  26:24|                Constant {value: 10}
  26:28|                Constant {value: 11}
>============================================================:py
  27|py:     
  28|py:     i = 0
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  28: 4|        Assign {targets: [Name], value: Constant}
  28: 4|W           Name {id: 'i'}
  28: 8|            Constant {value: 0}
>============================================================:py
  29|py:     d.a = zeros((2, 3))
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  29: 4|        Assign {targets: [Attribute], value: Call}
  29: 4|W           Attribute {value: Name, attr: 'a'}
  29: 4|R               Name {id: 'd'}
  29:10|            Call {func: Name, args: [Tuple], keywords: []}
  29:10|R               Name {id: 'zeros'}
  29:16|R               Tuple {elts: [Constant, Constant]}
  29:17|                    Constant {value: 2}
  29:20|                    Constant {value: 3}
>============================================================:py
  30|py:     d.a[i + 1][2] = 11.3
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  30: 4|        Assign {targets: [Subscript], value: Constant}
  30: 4|W           Subscript {value: Subscript, slice: Constant}
  30: 4|R               Subscript {value: Attribute, slice: BinOp}
  30: 4|R                   Attribute {value: Name, attr: 'a'}
  30: 4|R                       Name {id: 'd'}
  30: 8|                    BinOp {left: Name, op: Add, right: Constant}
  30: 8|R                       Name {id: 'i'}
       |                        Add {}
  30:12|                        Constant {value: 1}
  30:15|                Constant {value: 2}
  30:20|            Constant {value: 11.3}
>============================================================:py
  31|py:     d.a[1, d.x.y.z] = d.a[d.x.y.z + i]
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  31: 4|        Assign {targets: [Subscript], value: Subscript}
  31: 4|W           Subscript {value: Attribute, slice: Tuple}
  31: 4|R               Attribute {value: Name, attr: 'a'}
  31: 4|R                   Name {id: 'd'}
  31: 8|R               Tuple {elts: [Constant, Attribute]}
  31: 8|                    Constant {value: 1}
  31:11|R                   Attribute {value: Attribute, attr: 'z'}
  31:11|R                       Attribute {value: Attribute, attr: 'y'}
  31:11|R                           Attribute {value: Name, attr: 'x'}
  31:11|R                               Name {id: 'd'}
  31:22|R           Subscript {value: Attribute, slice: BinOp}
  31:22|R               Attribute {value: Name, attr: 'a'}
  31:22|R                   Name {id: 'd'}
  31:26|                BinOp {left: Attribute, op: Add, right: Name}
  31:26|R                   Attribute {value: Attribute, attr: 'z'}
  31:26|R                       Attribute {value: Attribute, attr: 'y'}
  31:26|R                           Attribute {value: Name, attr: 'x'}
  31:26|R                               Name {id: 'd'}
       |                    Add {}
  31:36|R                   Name {id: 'i'}
>============================================================:py
  32|py:     
  33|py:     a, b, c = 1, 2, 3
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  33: 4|        Assign {targets: [Tuple], value: Tuple}
  33: 4|W           Tuple {elts: [Name, Name, Name]}
  33: 4|W               Name {id: 'a'}
  33: 7|W               Name {id: 'b'}
  33:10|W               Name {id: 'c'}
  33:14|R           Tuple {elts: [Constant, Constant, Constant]}
  33:14|                Constant {value: 1}
  33:17|                Constant {value: 2}
  33:20|                Constant {value: 3}
>============================================================:py
  34|py:     y1, y2, y3 = func_A(d, 0)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  34: 4|        Assign {targets: [Tuple], value: Call}
  34: 4|W           Tuple {elts: [Name, Name, Name]}
  34: 4|W               Name {id: 'y1'}
  34: 8|W               Name {id: 'y2'}
  34:12|W               Name {id: 'y3'}
  34:17|            Call {func: Name, args: [Name, Constant], keywords: []}
  34:17|R               Name {id: 'func_A'}
  34:24|R               Name {id: 'd'}
  34:27|                Constant {value: 0}
>============================================================:py
  35|py:     
  36|py:     a = [1, 2, 3]
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  36: 4|        Assign {targets: [Name], value: List}
  36: 4|W           Name {id: 'a'}
  36: 8|R           List {elts: [Constant, Constant, Constant]}
  36: 9|                Constant {value: 1}
  36:12|                Constant {value: 2}
  36:15|                Constant {value: 3}
>============================================================:py
  37|py:     a = [i + 1 for i in range(10)]
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  37: 4|        Assign {targets: [Name], value: ListComp}
  37: 4|W           Name {id: 'a'}
  37: 8|            ListComp {elt: BinOp, generators: [comprehension]}
  37: 9|                BinOp {left: Name, op: Add, right: Constant}
  37: 9|R                   Name {id: 'i'}
       |                    Add {}
  37:13|                    Constant {value: 1}
       |                comprehension {target: Name, iter: Call, ifs: [], is_async: 0}
  37:19|W                   Name {id: 'i'}
  37:24|                    Call {func: Name, args: [Constant], keywords: []}
  37:24|R                       Name {id: 'range'}
  37:30|                        Constant {value: 10}
>============================================================:py
  38|py:     a = [i + 1 for i in range(10) if i > 5]
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  38: 4|        Assign {targets: [Name], value: ListComp}
  38: 4|W           Name {id: 'a'}
  38: 8|            ListComp {elt: BinOp, generators: [comprehension]}
  38: 9|                BinOp {left: Name, op: Add, right: Constant}
  38: 9|R                   Name {id: 'i'}
       |                    Add {}
  38:13|                    Constant {value: 1}
       |                comprehension {target: Name, iter: Call, ifs: [Compare], is_async: 0}
  38:19|W                   Name {id: 'i'}
  38:24|                    Call {func: Name, args: [Constant], keywords: []}
  38:24|R                       Name {id: 'range'}
  38:30|                        Constant {value: 10}
  38:37|                    Compare {left: Name, ops: [Gt], comparators: [Constant]}
  38:37|R                       Name {id: 'i'}
       |                        Gt {}
  38:41|                        Constant {value: 5}
>============================================================:py
  39|py:     a = {"a": 1, "b": a}
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  39: 4|        Assign {targets: [Name], value: Dict}
  39: 4|W           Name {id: 'a'}
  39: 8|            Dict {keys: [Constant, Constant], values: [Constant, Name]}
  39: 9|                Constant {value: 'a'}
  39:17|                Constant {value: 'b'}
  39:14|                Constant {value: 1}
  39:22|R               Name {id: 'a'}
>============================================================:py
  40|py:     
  41|py:     # ●行列
  42|py:     
  43|py:     d.a[0, :] = 1
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  43: 4|        Assign {targets: [Subscript], value: Constant}
  43: 4|W           Subscript {value: Attribute, slice: Tuple}
  43: 4|R               Attribute {value: Name, attr: 'a'}
  43: 4|R                   Name {id: 'd'}
  43: 8|R               Tuple {elts: [Constant, Slice]}
  43: 8|                    Constant {value: 0}
  43:11|                    Slice {lower: None, upper: None, step: None}
  43:16|            Constant {value: 1}
>============================================================:py
  44|py:     d.a[:, 1] += 13.4
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  44: 4|        AugAssign {target: Subscript, op: Add, value: Constant}
  44: 4|W           Subscript {value: Attribute, slice: Tuple}
  44: 4|R               Attribute {value: Name, attr: 'a'}
  44: 4|R                   Name {id: 'd'}
  44: 8|R               Tuple {elts: [Slice, Constant]}
  44: 8|                    Slice {lower: None, upper: None, step: None}
  44:11|                    Constant {value: 1}
       |            Add {}
  44:17|            Constant {value: 13.4}
>============================================================:py
  45|py:     d.a[1, 1:3] *= 14.4
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  45: 4|        AugAssign {target: Subscript, op: Mult, value: Constant}
  45: 4|W           Subscript {value: Attribute, slice: Tuple}
  45: 4|R               Attribute {value: Name, attr: 'a'}
  45: 4|R                   Name {id: 'd'}
  45: 8|R               Tuple {elts: [Constant, Slice]}
  45: 8|                    Constant {value: 1}
  45:11|                    Slice {lower: Constant, upper: Constant, step: None}
  45:11|                        Constant {value: 1}
  45:13|                        Constant {value: 3}
       |            Mult {}
  45:19|            Constant {value: 14.4}
>============================================================:py
  46|py:     d.b = d.a @ d.a.T
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  46: 4|        Assign {targets: [Attribute], value: BinOp}
  46: 4|W           Attribute {value: Name, attr: 'b'}
  46: 4|R               Name {id: 'd'}
  46:10|            BinOp {left: Attribute, op: MatMult, right: Attribute}
  46:10|R               Attribute {value: Name, attr: 'a'}
  46:10|R                   Name {id: 'd'}
       |                MatMult {}
  46:16|R               Attribute {value: Attribute, attr: 'T'}
  46:16|R                   Attribute {value: Name, attr: 'a'}
  46:16|R                       Name {id: 'd'}
>============================================================:py
  47|py:     d.b @= d.a
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  47: 4|        AugAssign {target: Attribute, op: MatMult, value: Attribute}
  47: 4|W           Attribute {value: Name, attr: 'b'}
  47: 4|R               Name {id: 'd'}
       |            MatMult {}
  47:11|R           Attribute {value: Name, attr: 'a'}
  47:11|R               Name {id: 'd'}
>============================================================:py
  48|py:     
  49|py:     # ●構文
  50|py:     
  51|py:     if d.x > 0:
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  51: 4|        If {test: Compare, body: [Assign, Return], orelse: [If]}
  51: 7|            Compare {left: Attribute, ops: [Gt], comparators: [Constant]}
  51: 7|R               Attribute {value: Name, attr: 'x'}
  51: 7|R                   Name {id: 'd'}
       |                Gt {}
  51:13|                Constant {value: 0}
>============================================================:py
  52|py:         d.y = y
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  52: 8|            Assign {targets: [Attribute], value: Name}
  52: 8|W               Attribute {value: Name, attr: 'y'}
  52: 8|R                   Name {id: 'd'}
  52:14|R               Name {id: 'y'}
>============================================================:py
  53|py:         return y
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  53: 8|            Return {value: Name}
  53:15|R               Name {id: 'y'}
>============================================================:py
  54|py:     elif y < 0 and \
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  54: 4|            If {test: BoolOp, body: [Return], orelse: [Pass]}
  54: 9|                BoolOp {op: Or, values: [BoolOp, UnaryOp]}
       |                    Or {}
  54: 9|                    BoolOp {op: And, values: [Compare, Compare]}
       |                        And {}
  54: 9|                        Compare {left: Name, ops: [Lt], comparators: [Constant]}
  54: 9|R                           Name {id: 'y'}
       |                            Lt {}
  54:13|                            Constant {value: 0}
>============================================================:py
  55|py:         y | x & a <= 0 or \
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  55: 8|                        Compare {left: BinOp, ops: [LtE], comparators: [Constant]}
  55: 8|                            BinOp {left: Name, op: BitOr, right: BinOp}
  55: 8|R                               Name {id: 'y'}
       |                                BitOr {}
  55:12|                                BinOp {left: Name, op: BitAnd, right: Name}
  55:12|R                                   Name {id: 'x'}
       |                                    BitAnd {}
  55:16|R                                   Name {id: 'a'}
       |                            LtE {}
  55:21|                            Constant {value: 0}
>============================================================:py
  56|py:         not y << 1 == 0:
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  56: 8|                    UnaryOp {op: Not, operand: Compare}
       |                        Not {}
  56:12|                        Compare {left: BinOp, ops: [Eq], comparators: [Constant]}
  56:12|                            BinOp {left: Name, op: LShift, right: Constant}
  56:12|R                               Name {id: 'y'}
       |                                LShift {}
  56:17|                                Constant {value: 1}
       |                            Eq {}
  56:22|                            Constant {value: 0}
>============================================================:py
  57|py:         return y
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  57: 8|                Return {value: Name}
  57:15|R                   Name {id: 'y'}
>============================================================:py
  58|py:     else:
  59|py:         pass
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  59: 8|                Pass {}
>============================================================:py
  60|py:     
  61|py:     b = \
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  61: 4|        Assign {targets: [Name], value: BinOp}
  61: 4|W           Name {id: 'b'}
>============================================================:py
  62|py:         tanh(b**2) + \
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  62: 8|            BinOp {left: Call, op: Add, right: Call}
  62: 8|                Call {func: Name, args: [BinOp], keywords: []}
  62: 8|R                   Name {id: 'tanh'}
  62:13|                    BinOp {left: Name, op: Pow, right: Constant}
  62:13|R                       Name {id: 'b'}
       |                        Pow {}
  62:16|                        Constant {value: 2}
       |                Add {}
>============================================================:py
  63|py:         tanh(b)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  63: 8|                Call {func: Name, args: [Name], keywords: []}
  63: 8|R                   Name {id: 'tanh'}
  63:13|R                   Name {id: 'b'}
>============================================================:py
  64|py:         
  65|py:     a_out = a.copy()
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  65: 4|        Assign {targets: [Name], value: Call}
  65: 4|W           Name {id: 'a_out'}
  65:12|            Call {func: Attribute, args: [], keywords: []}
  65:12|R               Attribute {value: Name, attr: 'copy'}
  65:12|R                   Name {id: 'a'}
>============================================================:py
  66|py:     for i_a in range(d.a[0], len(a) - 1, y):
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  66: 4|        For {target: Name, iter: Call, body: [Assign, Break, Continue], orelse: []}
  66: 8|W           Name {id: 'i_a'}
  66:15|            Call {func: Name, args: [Subscript, BinOp, Name], keywords: []}
  66:15|R               Name {id: 'range'}
  66:21|R               Subscript {value: Attribute, slice: Constant}
  66:21|R                   Attribute {value: Name, attr: 'a'}
  66:21|R                       Name {id: 'd'}
  66:25|                    Constant {value: 0}
  66:29|                BinOp {left: Call, op: Sub, right: Constant}
  66:29|                    Call {func: Name, args: [Name], keywords: []}
  66:29|R                       Name {id: 'len'}
  66:33|R                       Name {id: 'a'}
       |                    Sub {}
  66:38|                    Constant {value: 1}
  66:41|R               Name {id: 'y'}
>============================================================:py
  67|py:         a_out[i_a] = \
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  67: 8|            Assign {targets: [Subscript], value: BinOp}
  67: 8|W               Subscript {value: Name, slice: Name}
  67: 8|R                   Name {id: 'a_out'}
  67:14|R                   Name {id: 'i_a'}
>============================================================:py
  68|py:             tanh(a[i_a]**2) + \
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  68:12|                BinOp {left: Call, op: Add, right: Call}
  68:12|                    Call {func: Name, args: [BinOp], keywords: []}
  68:12|R                       Name {id: 'tanh'}
  68:17|                        BinOp {left: Subscript, op: Pow, right: Constant}
  68:17|R                           Subscript {value: Name, slice: Name}
  68:17|R                               Name {id: 'a'}
  68:19|R                               Name {id: 'i_a'}
       |                            Pow {}
  68:25|                            Constant {value: 2}
       |                    Add {}
>============================================================:py
  69|py:             tanh(a[i_a + 1])
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  69:12|                    Call {func: Name, args: [Subscript], keywords: []}
  69:12|R                       Name {id: 'tanh'}
  69:17|R                       Subscript {value: Name, slice: BinOp}
  69:17|R                           Name {id: 'a'}
  69:19|                            BinOp {left: Name, op: Add, right: Constant}
  69:19|R                               Name {id: 'i_a'}
       |                                Add {}
  69:25|                                Constant {value: 1}
>============================================================:py
  70|py:         break
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  70: 8|            Break {}
>============================================================:py
  71|py:         continue
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  71: 8|            Continue {}
>============================================================:py
  72|py: 
  73|py:     for i_a, a in enumerate(range(10)):
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  73: 4|        For {target: Tuple, iter: Call, body: [Expr], orelse: [Expr]}
  73: 8|W           Tuple {elts: [Name, Name]}
  73: 8|W               Name {id: 'i_a'}
  73:13|W               Name {id: 'a'}
  73:18|            Call {func: Name, args: [Call], keywords: []}
  73:18|R               Name {id: 'enumerate'}
  73:28|                Call {func: Name, args: [Constant], keywords: []}
  73:28|R                   Name {id: 'range'}
  73:34|                    Constant {value: 10}
>============================================================:py
  74|py:         func_A(a)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  74: 8|            Expr {value: Call}
  74: 8|                Call {func: Name, args: [Name], keywords: []}
  74: 8|R                   Name {id: 'func_A'}
  74:15|R                   Name {id: 'a'}
>============================================================:py
  75|py:     else:
  76|py:         func_A(a)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  76: 8|            Expr {value: Call}
  76: 8|                Call {func: Name, args: [Name], keywords: []}
  76: 8|R                   Name {id: 'func_A'}
  76:15|R                   Name {id: 'a'}
>============================================================:py
  77|py: 
  78|py:     for i_a, (a, b) in enumerate(zip(range(10), range(5))):
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  78: 4|        For {target: Tuple, iter: Call, body: [Pass], orelse: []}
  78: 8|W           Tuple {elts: [Name, Tuple]}
  78: 8|W               Name {id: 'i_a'}
  78:13|W               Tuple {elts: [Name, Name]}
  78:14|W                   Name {id: 'a'}
  78:17|W                   Name {id: 'b'}
  78:23|            Call {func: Name, args: [Call], keywords: []}
  78:23|R               Name {id: 'enumerate'}
  78:33|                Call {func: Name, args: [Call, Call], keywords: []}
  78:33|R                   Name {id: 'zip'}
  78:37|                    Call {func: Name, args: [Constant], keywords: []}
  78:37|R                       Name {id: 'range'}
  78:43|                        Constant {value: 10}
  78:48|                    Call {func: Name, args: [Constant], keywords: []}
  78:48|R                       Name {id: 'range'}
  78:54|                        Constant {value: 5}
>============================================================:py
  79|py:         pass
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  79: 8|            Pass {}
>============================================================:py
  80|py:     
  81|py:     while y > 0:
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  81: 4|        While {test: Compare, body: [Break, Continue], orelse: []}
  81:10|            Compare {left: Name, ops: [Gt], comparators: [Constant]}
  81:10|R               Name {id: 'y'}
       |                Gt {}
  81:14|                Constant {value: 0}
>============================================================:py
  82|py:         break
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  82: 8|            Break {}
>============================================================:py
  83|py:         continue
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  83: 8|            Continue {}
>============================================================:py
  84|py:     
  85|py:     return a
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  85: 4|        Return {value: Name}
  85:11|R           Name {id: 'a'}
>============================================================:py
  86|py:     
  87|py:     # ●内包
  88|py:     
  89|py:     def func_A(a):
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  89: 4|        FunctionDef {name: 'func_A', args: arguments, body: [Return], decorator_list: [], returns: None}
       |            arguments {args: [arg], vararg: None, kwonlyargs: [], kw_defaults: [], kwarg: None, defaults: []}
  89:15|                arg {arg: 'a', annotation: None}
>============================================================:py
  90|py:         return a
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  90: 8|            Return {value: Name}
  90:15|R               Name {id: 'a'}
>============================================================:py
  91|py:     func_A(a)
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  91: 4|        Expr {value: Call}
  91: 4|            Call {func: Name, args: [Name], keywords: []}
  91: 4|R               Name {id: 'func_A'}
  91:11|R               Name {id: 'a'}
>============================================================:py
  92|py:     
  93|py:     class Data11: pass
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  93: 4|        ClassDef {name: 'Data11', bases: [], keywords: [], body: [Pass], decorator_list: []}
  93:18|            Pass {}
>============================================================:py
  94|py:     a = Data11()
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  94: 4|        Assign {targets: [Name], value: Call}
  94: 4|W           Name {id: 'a'}
  94: 8|            Call {func: Name, args: [], keywords: []}
  94: 8|R               Name {id: 'Data11'}
>============================================================:py
  95|py: 
  96|py: # ●関数
  97|py: 
  98|py: def func_A(
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  98: 0|    FunctionDef {name: 'func_A', args: arguments, body: [Return], decorator_list: [], returns: None}
       |        arguments {args: [arg, arg, arg, arg], vararg: None, kwonlyargs: [], kw_defaults: [], kwarg: None, defaults: [Constant, Constant, Constant]}
>============================================================:py
  99|py:     d, 
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
  99: 4|            arg {arg: 'd', annotation: None}
>============================================================:py
 100|py:     x = 0,
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 100: 4|            arg {arg: 'x', annotation: None}
>============================================================:py
 101|py:     x2 = 0,
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 101: 4|            arg {arg: 'x2', annotation: None}
>============================================================:py
 102|py:     x3 = 0):
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 102: 4|            arg {arg: 'x3', annotation: None}
 100: 8|            Constant {value: 0}
 101: 9|            Constant {value: 0}
 102: 9|            Constant {value: 0}
>============================================================:py
 103|py:     
 104|py:     return 2 * x + d.x, x**2, x**3
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 104: 4|        Return {value: Tuple}
 104:11|R           Tuple {elts: [BinOp, BinOp, BinOp]}
 104:11|                BinOp {left: BinOp, op: Add, right: Attribute}
 104:11|                    BinOp {left: Constant, op: Mult, right: Name}
 104:11|                        Constant {value: 2}
       |                        Mult {}
 104:15|R                       Name {id: 'x'}
       |                    Add {}
 104:19|R                   Attribute {value: Name, attr: 'x'}
 104:19|R                       Name {id: 'd'}
 104:24|                BinOp {left: Name, op: Pow, right: Constant}
 104:24|R                   Name {id: 'x'}
       |                    Pow {}
 104:27|                    Constant {value: 2}
 104:30|                BinOp {left: Name, op: Pow, right: Constant}
 104:30|R                   Name {id: 'x'}
       |                    Pow {}
 104:33|                    Constant {value: 3}
>============================================================:py
 105|py: 
 106|py: class Data1: pass
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 106: 0|    ClassDef {name: 'Data1', bases: [], keywords: [], body: [Pass], decorator_list: []}
 106:13|        Pass {}
>============================================================:py
 107|py: class Data2: pass
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 107: 0|    ClassDef {name: 'Data2', bases: [], keywords: [], body: [Pass], decorator_list: []}
 107:13|        Pass {}
>============================================================:py
 108|py: class Data3: pass
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 108: 0|    ClassDef {name: 'Data3', bases: [], keywords: [], body: [Pass], decorator_list: []}
 108:13|        Pass {}
>============================================================:py
 109|py: 
 110|py: # ●クラス
 111|py: 
 112|py: class Data(
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 112: 0|    ClassDef {name: 'Data', bases: [Name, Name, Name], keywords: [], body: [Assign, FunctionDef, FunctionDef, FunctionDef], decorator_list: []}
>============================================================:py
 113|py:     Data1, 
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 113: 4|R       Name {id: 'Data1'}
>============================================================:py
 114|py:     Data2, 
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 114: 4|R       Name {id: 'Data2'}
>============================================================:py
 115|py:     Data3):
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 115: 4|R       Name {id: 'Data3'}
>============================================================:py
 116|py:     
 117|py:     # sec: 初期化
 118|py:     
 119|py:     gb_a = 1
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 119: 4|        Assign {targets: [Name], value: Constant}
 119: 4|W           Name {id: 'gb_a'}
 119:11|            Constant {value: 1}
>============================================================:py
 120|py:     
 121|py:     def __init__(self):
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 121: 4|        FunctionDef {name: '__init__', args: arguments, body: [Assign, Assign], decorator_list: [], returns: None}
       |            arguments {args: [arg], vararg: None, kwonlyargs: [], kw_defaults: [], kwarg: None, defaults: []}
 121:17|                arg {arg: 'self', annotation: None}
>============================================================:py
 122|py:         self.a = 12.34
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 122: 8|            Assign {targets: [Attribute], value: Constant}
 122: 8|W               Attribute {value: Name, attr: 'a'}
 122: 8|R                   Name {id: 'self'}
 122:17|                Constant {value: 12.34}
>============================================================:py
 123|py:         self.b = self.a**2
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 123: 8|            Assign {targets: [Attribute], value: BinOp}
 123: 8|W               Attribute {value: Name, attr: 'b'}
 123: 8|R                   Name {id: 'self'}
 123:17|                BinOp {left: Attribute, op: Pow, right: Constant}
 123:17|R                   Attribute {value: Name, attr: 'a'}
 123:17|R                       Name {id: 'self'}
       |                    Pow {}
 123:25|                    Constant {value: 2}
>============================================================:py
 124|py:     
 125|py:     # sec: 機能群
 126|py:     
 127|py:     def func_A(self):
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 127: 4|        FunctionDef {name: 'func_A', args: arguments, body: [Return], decorator_list: [], returns: None}
       |            arguments {args: [arg], vararg: None, kwonlyargs: [], kw_defaults: [], kwarg: None, defaults: []}
 127:15|                arg {arg: 'self', annotation: None}
>============================================================:py
 128|py:         return self.a + self.gb_a
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 128: 8|            Return {value: BinOp}
 128:15|                BinOp {left: Attribute, op: Add, right: Attribute}
 128:15|R                   Attribute {value: Name, attr: 'a'}
 128:15|R                       Name {id: 'self'}
       |                    Add {}
 128:24|R                   Attribute {value: Name, attr: 'gb_a'}
 128:24|R                       Name {id: 'self'}
>============================================================:py
 129|py:             
 130|py:     def func_B(self, x, y):
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 130: 4|        FunctionDef {name: 'func_B', args: arguments, body: [ClassDef, Return], decorator_list: [], returns: None}
       |            arguments {args: [arg, arg, arg], vararg: None, kwonlyargs: [], kw_defaults: [], kwarg: None, defaults: []}
 130:15|                arg {arg: 'self', annotation: None}
 130:21|                arg {arg: 'x', annotation: None}
 130:24|                arg {arg: 'y', annotation: None}
>============================================================:py
 131|py:         class Data11: pass
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 131: 8|            ClassDef {name: 'Data11', bases: [], keywords: [], body: [Pass], decorator_list: []}
 131:22|                Pass {}
>============================================================:py
 132|py:         return self.a * self.b + x / y + x // y + x % y
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 132: 8|            Return {value: BinOp}
 132:15|                BinOp {left: BinOp, op: Add, right: BinOp}
 132:15|                    BinOp {left: BinOp, op: Add, right: BinOp}
 132:15|                        BinOp {left: BinOp, op: Add, right: BinOp}
 132:15|                            BinOp {left: Attribute, op: Mult, right: Attribute}
 132:15|R                               Attribute {value: Name, attr: 'a'}
 132:15|R                                   Name {id: 'self'}
       |                                Mult {}
 132:24|R                               Attribute {value: Name, attr: 'b'}
 132:24|R                                   Name {id: 'self'}
       |                            Add {}
 132:33|                            BinOp {left: Name, op: Div, right: Name}
 132:33|R                               Name {id: 'x'}
       |                                Div {}
 132:37|R                               Name {id: 'y'}
       |                        Add {}
 132:41|                        BinOp {left: Name, op: FloorDiv, right: Name}
 132:41|R                           Name {id: 'x'}
       |                            FloorDiv {}
 132:46|R                           Name {id: 'y'}
       |                    Add {}
 132:50|                    BinOp {left: Name, op: Mod, right: Name}
 132:50|R                       Name {id: 'x'}
       |                        Mod {}
 132:54|R                       Name {id: 'y'}
>============================================================:py
 133|py: 
 134|py: # sec: entry
 135|py: 
 136|py: if __name__ == "__main__":
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 136: 0|    If {test: Compare, body: [Expr], orelse: []}
 136: 3|        Compare {left: Name, ops: [Eq], comparators: [Constant]}
 136: 3|R           Name {id: '__name__'}
       |            Eq {}
 136:15|            Constant {value: '__main__'}
>============================================================:py
 137|py:     main()
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - :ast
 137: 4|        Expr {value: Call}
 137: 4|            Call {func: Name, args: [], keywords: []}
 137: 4|R               Name {id: 'main'}
```

この時、サンプルとして使用したPythonの元コードは、(特に意味のない適当なコード)

```py:サンプル用のPythonの元コード
# -*- coding: utf-8 -*-

import numpy
import numpy as np
from numpy import random, a, b, c
from numpy import *
import scipy
import matplotlib.pyplot as plt

# sec: main

def main():

    # ●式
    
    d = Data() # データ格納オブジェクト
    d.x = Data(0xABC)
    d.x.y = Data(0b1010_1111, numpy.a)
    d.x.y.z = 0
    
    func_A(d, 0)
    y = func_A(d, 0)
    f = lambda x: x**2

    a = numpy.a.b.c.arange(0, 1, 0.1, dtype=numpy.float) # 名前空間参照
    a[0], a[1+2*3**4] = 10, 11
    
    i = 0
    d.a = zeros((2, 3))
    d.a[i + 1][2] = 11.3
    d.a[1, d.x.y.z] = d.a[d.x.y.z + i]
    
    a, b, c = 1, 2, 3
    y1, y2, y3 = func_A(d, 0)
    
    a = [1, 2, 3]
    a = [i + 1 for i in range(10)]
    a = [i + 1 for i in range(10) if i > 5]
    a = {"a": 1, "b": a}
    
    # ●行列
    
    d.a[0, :] = 1
    d.a[:, 1] += 13.4
    d.a[1, 1:3] *= 14.4
    d.b = d.a @ d.a.T
    d.b @= d.a
    
    # ●構文
    
    if d.x > 0:
        d.y = y
        return y
    elif y < 0 and \
        y | x & a <= 0 or \
        not y << 1 == 0:
        return y
    else:
        pass
    
    b = \
        tanh(b**2) + \
        tanh(b)
        
    a_out = a.copy()
    for i_a in range(d.a[0], len(a) - 1, y):
        a_out[i_a] = \
            tanh(a[i_a]**2) + \
            tanh(a[i_a + 1])
        break
        continue

    for i_a, a in enumerate(range(10)):
        func_A(a)
    else:
        func_A(a)

    for i_a, (a, b) in enumerate(zip(range(10), range(5))):
        pass
    
    while y > 0:
        break
        continue
    
    return a
    
    # ●内包
    
    def func_A(a):
        return a
    func_A(a)
    
    class Data11: pass
    a = Data11()

# ●関数

def func_A(
    d, 
    x = 0,
    x2 = 0,
    x3 = 0):
    
    return 2 * x + d.x, x**2, x**3

class Data1: pass
class Data2: pass
class Data3: pass

# ●クラス

class Data(
    Data1, 
    Data2, 
    Data3):
    
    # sec: 初期化
    
    gb_a = 1
    
    def __init__(self):
        self.a = 12.34
        self.b = self.a**2
    
    # sec: 機能群
    
    def func_A(self):
        return self.a + self.gb_a
            
    def func_B(self, x, y):
        class Data11: pass
        return self.a * self.b + x / y + x // y + x % y

# sec: entry

if __name__ == "__main__":
    main()
```


#   環境

Python 3.9.5 (tags/v3.9.5:0a7dcbd, May 3 2021) [MSC v.1928 64 bit (AMD64)] on Win 10