Pythonを解読する:抽象構文木(AST)を使ってコードを理解する方法
プログラミングについて少しメタ化しましょう.
どのようにPythonプログラム(より良いインタプリタとして知っている)“どのようにコードを実行する”を知っていますか?あなたがプログラミングに新しいならば、それは魔法のように見えるかもしれません.実際には、それはまだ私に10年以上の専門家である後に魔法のようです.
Pythonインタプリタは魔法ではありません.それはあなたのコードを機械が動くことができる指示に翻訳するステップの予測可能なセットに続きます.
かなり高いレベルで、あなたのコードに起こることは以下の通りです. コードは通常トークンと呼ばれる部分のリストに解析されます.これらのトークンは、異なる扱い方をするためのルールのセットに基づいています.例えば、キーワード トークンの生のリストは抽象的な構文木、ASTを構築するために変換されます.ASTはPython言語の文法に基づいてリンクされたノードの集まりです.私たちが瞬間的にそれ以上の光を輝かせるので、それが今意味をなさないならば、心配しないでください. 抽象構文木から、インタプリタはバイトコードと呼ばれる低いレベルの命令を生成できます.これらの指示は バイトコード命令が利用できるので、インタプリタは最終的にコードを実行できます.バイトコードは、プログラムを実行するためにCPUとメモリと最終的に対話するオペレーティングシステムの関数を呼び出すために使用されます. その詳細についてはもっと詳細に説明することができましたが、それはどのように入力された文字がコンピュータのCPUによって実行されるかのラフスケッチです.
解析ツールとしてのAST
あなたのソースコードがバイトコードに変えられる時までには、あなたが書いたものについての理解を得るには遅すぎる.バイトコードは非常に原始的であり、非常に高速のインタプリタを作るために調整されます.言い換えると、バイトコードは人々の上でコンピュータのために設計されます.
一方、抽象構文木は、コードの学習に役立つように十分な構造情報を持っています.しかし、彼らはバイトコード表現より賢明です.
Pythonは“バッテリー含まれている”言語であるため、あなたが使用する必要があるツールは、標準ライブラリに組み込まれています.
ASTで動作する主なツールは
以下はthe example Python script それを使用します.このスクリプトは“モジュールがインポートされたものの質問に答えますか?”
Pythonファイルのテキスト(この場合、例のコードそのもの)を抽象構文木に変換します. ASTを分析して情報を抽出します. 次のコードを実行できます.
に変換
つの関数呼び出しで、Pythonはすべてのトークンを処理し、言語のすべての規則に従って、コードを実行するために関連するすべての情報を含むデータ構造を構築しました.
移動する前に、木が何であるかについて考えるために、ちょっと時間を計ろう.木はソフトウェア開発における非常に深い話題であるので、これは徹底的な説明よりむしろプライマーを考慮します.
このツリーをコードで表現する一つの方法は次のようになります.
分析する
一度、私たちは木を持っている
私は、Python ASTが私の基本より複雑である点に注意しました
エー
私の例のコードはインポートについて調べることです.インポートについて学ぶために、コードは
と
では、どのような種類のノード型が存在するのでしょうか?あなたは完全なリストを見つけることができますAbstract Grammar セクション
ラッピング
さて、どうすればいいのでしょうか PythonソースコードからASTをビルドします. Aを用いたAST解析 抽象構文木を使って、あなたのコードについて多くの興味深い質問に答えることができます.次のようになります. どのように多くの変数を使用しましたか? 私のコードで最も一般的な関数呼び出しは何ですか? 私のモジュールはしっかりとお互いに結合していますか? どのサードパーティライブラリが異なるパッケージで頻繁に表示されますか? The
あなたがこの役に立つとわかるならば、あなたはTwitterまたはあなたの大好きな社会的メディア・サイトでこれを共有したいですか?私はこれらのトピックについての人々とチャットするのが好きですので、私をさえずること自由に感じてください.
どのようにPythonプログラム(より良いインタプリタとして知っている)“どのようにコードを実行する”を知っていますか?あなたがプログラミングに新しいならば、それは魔法のように見えるかもしれません.実際には、それはまだ私に10年以上の専門家である後に魔法のようです.
Pythonインタプリタは魔法ではありません.それはあなたのコードを機械が動くことができる指示に翻訳するステップの予測可能なセットに続きます.
かなり高いレベルで、あなたのコードに起こることは以下の通りです.
if
のような数値より異なるトークンです42
. BINARY_ADD
そして、コンピュータがそれらを走らせることができるように、非常に一般的であるはずです.解析ツールとしてのAST
あなたのソースコードがバイトコードに変えられる時までには、あなたが書いたものについての理解を得るには遅すぎる.バイトコードは非常に原始的であり、非常に高速のインタプリタを作るために調整されます.言い換えると、バイトコードは人々の上でコンピュータのために設計されます.
一方、抽象構文木は、コードの学習に役立つように十分な構造情報を持っています.しかし、彼らはバイトコード表現より賢明です.
Pythonは“バッテリー含まれている”言語であるため、あなたが使用する必要があるツールは、標準ライブラリに組み込まれています.
ASTで動作する主なツールは
ast
モジュールです.例を見てみましょう.ast
例によって以下はthe example Python script それを使用します.このスクリプトは“モジュールがインポートされたものの質問に答えますか?”
import ast
from pprint import pprint
def main():
with open("ast_example.py", "r") as source:
tree = ast.parse(source.read())
analyzer = Analyzer()
analyzer.visit(tree)
analyzer.report()
class Analyzer(ast.NodeVisitor):
def __init__(self):
self.stats = {"import": [], "from": []}
def visit_Import(self, node):
for alias in node.names:
self.stats["import"].append(alias.name)
self.generic_visit(node)
def visit_ImportFrom(self, node):
for alias in node.names:
self.stats["from"].append(alias.name)
self.generic_visit(node)
def report(self):
pprint(self.stats)
if __name__ == "__main__":
main()
このコードはいくつかの主要な事柄を行います.$ python3 ast_example.py
{'from': ['pprint'], 'import': ['ast']}
に変換
with open("ast_example.py", "r") as source:
tree = ast.parse(source.read())
2行のコードで、ファイルを読んで、ASTという名前を作成しますtree
. The ast.parse
機能は、このスナップになります!その機能のフードの下で、我々は至福を無視することができるトンが起こっている.つの関数呼び出しで、Pythonはすべてのトークンを処理し、言語のすべての規則に従って、コードを実行するために関連するすべての情報を含むデータ構造を構築しました.
移動する前に、木が何であるかについて考えるために、ちょっと時間を計ろう.木はソフトウェア開発における非常に深い話題であるので、これは徹底的な説明よりむしろプライマーを考慮します.
A tree is a way to hold data as a set of "nodes" connected by "edges."
+-----+
| A |
+-----+
/ \
/ \
+-----+ +-----+
| B | | C |
+-----+ +-----+
この図において、A,B,Cは全てノードであり、A〜BとA〜Cとを接続する辺がある.このツリーをコードで表現する一つの方法は次のようになります.
class Node:
def __init__(self, value):
self.value = value
self.children = []
tree = Node('A')
tree.children.append(Node('B'))
tree.children.append(Node('C'))
注意tree
実際にノードです!木で作業するとき、私たちは本当にノードのコレクションを扱っています、そして、木の変数は「ルート」ノード(例えば、ノードA)へのリファレンスです.この種の構造を持つことによって、木の各ノードをチェックして、行動を起こすことができます.ツリー内の各ノードを訪問し、そのデータを処理することによって行う.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
木が何であるかという考えがあるので、我々は例のスクリプトの次のセクションが何をするかについて考慮することができます.Python抽象構文木のツリー構造は、ノード数とデータの型のためにより関係がありますが、ノードとエッジのコアアイデアは同じです.分析する
一度、私たちは木を持っている
Analyzer
ツリーから情報を抽出するために上記の訪問者パターンに従います.私は、Python ASTが私の基本より複雑である点に注意しました
Node
デザイン.つの違いは、それが様々な種類のノードを追跡するということです.ここはどこですast.NodeVisitor
が便利です.エー
NodeVisitor
Python AST内の任意のノードに対応できます.特定の種類のノードを訪問するには、以下のような方法を実装しなければなりませんvisit_<node type>
.私の例のコードはインポートについて調べることです.インポートについて学ぶために、コードは
Import
and ImportFrom
ノードの種類.def visit_Import(self, node):
for alias in node.names:
self.stats["import"].append(alias.name)
self.generic_visit(node)
def visit_ImportFrom(self, node):
for alias in node.names:
self.stats["from"].append(alias.name)
self.generic_visit(node)
このコードは、モジュールの名前を受け取り、統計情報の一覧に格納します.コードが空想でない間、ASTノードと対話する方法を示します.と
NodeVisitor
クラスを定義すると、ツリーを解析するために使用できます.analyzer = Analyzer()
analyzer.visit(tree)
The visit
メソッドはvisit_<node type>
ツリー構造を横切って横切っている間、そのタイプのノードが遭遇するときはいつでも、メソッド.では、どのような種類のノード型が存在するのでしょうか?あなたは完全なリストを見つけることができますAbstract Grammar セクション
ast
モジュールドキュメント.正直、私はそのドキュメントを少し吸収するのが難しいとわかります.あなたのようなより徹底的なガイドを参照してより多くの成功を持っている可能性がありますGreen Tree Snakes ノードガイド.ラッピング
さて、どうすればいいのでしょうか
NodeVisitor
. ast
モジュールはおそらく非常に頻繁に到達するツールではありません.必要な時にはast
, その最小限のAPIはかなり記憶に残るとすぐにコードを分析することができます.あなたがこの役に立つとわかるならば、あなたはTwitterまたはあなたの大好きな社会的メディア・サイトでこれを共有したいですか?私はこれらのトピックについての人々とチャットするのが好きですので、私をさえずること自由に感じてください.
Reference
この問題について(Pythonを解読する:抽象構文木(AST)を使ってコードを理解する方法), 我々は、より多くの情報をここで見つけました https://dev.to/mblayman/deciphering-python-how-to-use-abstract-syntax-trees-ast-to-understand-code-gfmテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol