Python ast模塊

在本教程中,我們將學習如何使用 AST 來理解代碼。

什麼是 ast模塊?

AST 代表抽象語法樹,,它是 Python 編程語言的有力工具。它允許我們與 Python 代碼本身進行交互,並可以對其進行修改。

你有沒有想過 Python 代碼是如何運行的?背後有魔法嗎?

對於不知道的人,Python 解釋器負責運行 Python 代碼。它遵循預先編寫的指令,將 Python 代碼翻譯成機器可以運行的指令。

下面是將 Python 代碼轉換為機器代碼的過程。

  • 當我們運行代碼時,代碼被解析成稱為標記的更小的塊。這些令牌是由應該區別對待的預定義指令創建的。例如,關鍵字或是不同於數值的關鍵字,如
  • 令牌存儲在轉換後的列表中,以構建抽象語法樹。AST 是基於 Python 語言語法鏈接在一起的兩個或多個節點的集合。
  • 編譯器可以從 AST 產生稱為二進制代碼的低級指令。這段代碼非常通用,因此計算機可以輕鬆運行。
  • 當解釋器得到類似字節碼的指令時,解釋器現在可以運行代碼了。字節碼負責在操作系統中調用函數,最終將與 CPU 和內存交互運行程序。

上面的描述是解釋器如何使用 AST 運行 Python 代碼的粗略草圖。

代碼編譯模式

有三種模式可以編譯代碼。它們如下所示。

  • exec – 該模式用於執行正常的 Python 代碼。
  • eval – 該模式用於評估 Python 的表達式,評估後會返回結果。
  • single – 該模式作為 Python shell 工作,一次執行一條語句。

執行 Python 代碼

使用 ast模塊,我們可以運行 Python 代碼。讓我們理解下面的例子。

示例-


import ast

code = ast.parse("print('Hello Learner ! Welcome to JavaTpoint')")
print(code)

exec(compile(code, filename="", mode="exec"))

輸出:

<_ast.module object="" at="">
Hello Learner! Welcome to JavaTpoint

評估 Python 表達式

ast模塊允許我們評估 Python 表達式,並從表達式中返回結果。讓我們理解下面的例子。

示例-


import ast

expression = '6 + 8'
code = ast.parse(expression, mode='eval')

print(eval(compile(code, '', mode='eval')))
print(ast.dump(code))

輸出:

14
Expression(body=BinOp(left=Constant(value=6, kind=None), op=Add(), right=Constant(value=8, kind=None)))

創建多行 ASTs

在前面的例子中,我們已經看到了單行 AST 以及如何轉儲它們。現在,我們將學習如何創建多行 AST。首先,讓我們理解下面的例子。

示例-


import ast

tree_ast = ast.parse('''
subjects = ['computer science', 'alorithm']
name = 'Ricky'

for sub in subjects:
    print('{} learn {}'.format(name, subjects))
''')

print(ast.dump(tree_ast))

輸出:

Module(body=[Assign(targets=[Name(id='subjects', ctx=Store())], value=List(elts=[Constant(value='computer science', kind=None), Constant(value='alorithm', kind=None)], ctx=Load()), type_comment=None), Assign(targets=[Name(id='name', ctx=Store())], value=Constant(value='Ricky', kind=None), type_comment=None), For(target=Name(id='fruit', ctx=Store()), iter=Name(id='fruits', ctx=Load()), body=[Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Call(func=Attribute(value=Constant(value='{} learn {}', kind=None), attr='format', ctx=Load()), args=[Name(id='name', ctx=Load()), Name(id='subjects', ctx=Load())], keywords=[])], keywords=[]))], orelse=[], type_comment=None)], type_ignores=[])

節點轉換器和節點訪問者

節點變壓器類用於根據我們的要求採取不同的類型和修改。ast 模塊還提供了 NodeVisitor 類,幫助我們在每次遍歷樹的時候調用訪問函數。為了更好地控制節點,我們來理解下面的例子。

示例- 1


import ast
class Visitor(ast.NodeVisitor):
    def visit_Str(self, node):
        print('String Node: "' + node.s + '"')

class MyTransformer(ast.NodeTransformer):
    def visit_Str(self, node):
        return ast.Str('str: ' + node.s)

parsed = ast.parse("print('Hello World')")
MyTransformer().visit(parsed)
Visitor().visit(parsed)

輸出:

Welcome to the Javatpoint

解釋-

在上面的代碼中,我們已經導入了解析代碼的 ast 模塊。然後我們定義了繼承了節點訪問者類的訪問者類。每次找到字符串節點;它通過添加前綴而被轉換。

當我們直接運行源代碼時,我們也可以使用該模塊。讓我們理解下面的例子。

示例- 2:


import ast
from pprint import pprint

def main():
    with open("ast_module.py", "r") as source:
        ast_tree = ast.parse(source.read())

    analysis = Analyzer()
    analysis.visit(ast_tree)
    analysis.report()

class Analyzer(ast.NodeVisitor):
    def __init__(self):
        self.stats = {"import": [], "from": []}

    def node_visit(self, node):
        for alias in node.names:
            self.stats["import"].append(alias.name)
        self.generic_visit(node)

    def node_visitFrom(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__":

輸出:

{'from': ['pprint'], 'import': ['ast']}

解釋-

上面的代碼將 Python 文件轉換為抽象語法樹。然後我們分析樹以獲得有用的信息。

我們已經在讀取模式下打開了一個 Python 文件,然後創建了一個名為 ast_tree 的 AST。然後, parse() 函數處理所有的標記,遵循所有的語言規則,並構建一個包含大量有用信息的樹形數據結構。

樹只不過是節點的集合,其中一個樹變量引用了“根”節點。因此,我們可以訪問樹中的每個節點並執行操作。但是,首先,我們訪問每個節點並處理數據。

分析 AST

一旦我們得到樹,現在分析器遵循訪問者模式。使用節點訪問者類,我們可以跟蹤 Python 中的任何節點。我們需要實現一個方法訪問 _ <節點類型> 來訪問特定的節點類型。在前面的例子中,我們使用了下面的腳本。

示例-


class Analyzer(ast.NodeVisitor):
    def node_visit(self, node):
            for alias in node.names:
                self.stats["import"].append(alias.name)
            self.generic_visit(node)

    def node_visitFrom(self, node):
           for alias in node.names:
                self.stats["from"].append(alias.name)
          self.generic_visit(node)

代碼接受模塊的名稱,並將其存儲在統計列表中。藉助 NodeVisitor 類,我們可以對樹進行分析。


analyzer = Analyzer()
analyzer.visit(tree)

visit()方法的工作原理與 visit_ <節點類型> 方法相同。

使用 AST 作為分析工具

Python 代碼變成字節碼後,人類無法讀取。但它使解釋器變得更快,這意味着字節碼是為機器設計的,而不是為人類設計的。

AST 由足夠多的結構化信息組成,這使得它們有助於學習 Python 代碼。然而,ASTs 仍然不是用戶友好的,但是它們比字節代碼表示更容易理解。

什麼時候用 Python ast模塊?

抽象語法樹對代碼覆蓋工具很有幫助。它解析源代碼,發現代碼中可能存在的缺陷和錯誤。它也可以用在-

  • 它被用作定製的 Python 解釋器。
  • 它用於分析靜態代碼。
  • 它使 IDEs 變得智能,這就是所謂的智能感知。

結論

我們已經了解了 Python 中負責運行 Python 代碼的 ast 模塊。然後,我們從 Python 代碼中構建了 AST 樹,並使用節點訪問者類對 AST 進行了分析。


原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/296254.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-27 12:58
下一篇 2024-12-27 12:58

相關推薦

  • Python周杰倫代碼用法介紹

    本文將從多個方面對Python周杰倫代碼進行詳細的闡述。 一、代碼介紹 from urllib.request import urlopen from bs4 import Bea…

    編程 2025-04-29
  • Python計算陽曆日期對應周幾

    本文介紹如何通過Python計算任意陽曆日期對應周幾。 一、獲取日期 獲取日期可以通過Python內置的模塊datetime實現,示例代碼如下: from datetime imp…

    編程 2025-04-29
  • 如何查看Anaconda中Python路徑

    對Anaconda中Python路徑即conda環境的查看進行詳細的闡述。 一、使用命令行查看 1、在Windows系統中,可以使用命令提示符(cmd)或者Anaconda Pro…

    編程 2025-04-29
  • Python中引入上一級目錄中函數

    Python中經常需要調用其他文件夾中的模塊或函數,其中一個常見的操作是引入上一級目錄中的函數。在此,我們將從多個角度詳細解釋如何在Python中引入上一級目錄的函數。 一、加入環…

    編程 2025-04-29
  • Python列表中負數的個數

    Python列表是一個有序的集合,可以存儲多個不同類型的元素。而負數是指小於0的整數。在Python列表中,我們想要找到負數的個數,可以通過以下幾個方面進行實現。 一、使用循環遍歷…

    編程 2025-04-29
  • Python字典去重複工具

    使用Python語言編寫字典去重複工具,可幫助用戶快速去重複。 一、字典去重複工具的需求 在使用Python編寫程序時,我們經常需要處理數據文件,其中包含了大量的重複數據。為了方便…

    編程 2025-04-29
  • Python清華鏡像下載

    Python清華鏡像是一個高質量的Python開發資源鏡像站,提供了Python及其相關的開發工具、框架和文檔的下載服務。本文將從以下幾個方面對Python清華鏡像下載進行詳細的闡…

    編程 2025-04-29
  • 蝴蝶優化算法Python版

    蝴蝶優化算法是一種基於仿生學的優化算法,模仿自然界中的蝴蝶進行搜索。它可以應用於多個領域的優化問題,包括數學優化、工程問題、機器學習等。本文將從多個方面對蝴蝶優化算法Python版…

    編程 2025-04-29
  • Python程序需要編譯才能執行

    Python 被廣泛應用於數據分析、人工智能、科學計算等領域,它的靈活性和簡單易學的性質使得越來越多的人喜歡使用 Python 進行編程。然而,在 Python 中程序執行的方式不…

    編程 2025-04-29
  • python強行終止程序快捷鍵

    本文將從多個方面對python強行終止程序快捷鍵進行詳細闡述,並提供相應代碼示例。 一、Ctrl+C快捷鍵 Ctrl+C快捷鍵是在終端中經常用來強行終止運行的程序。當你在終端中運行…

    編程 2025-04-29

發表回復

登錄後才能評論