溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

python的簡(jiǎn)單四則運(yùn)算語(yǔ)法樹(shù)可視化如何實(shí)現(xiàn)

發(fā)布時(shí)間:2023-05-11 10:38:17 來(lái)源:億速云 閱讀:128 作者:zzz 欄目:編程語(yǔ)言

本篇內(nèi)容介紹了“python的簡(jiǎn)單四則運(yùn)算語(yǔ)法樹(shù)可視化如何實(shí)現(xiàn)”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

簡(jiǎn)單四則運(yùn)算語(yǔ)法樹(shù)可視化

如果想要?jiǎng)邮謬L試一下,需要安裝一下這個(gè) python 可視化庫(kù)。

python的簡(jiǎn)單四則運(yùn)算語(yǔ)法樹(shù)可視化如何實(shí)現(xiàn)

解析 AST

Python 的 ast 庫(kù)有一個(gè) parse 方法,可以把傳入的內(nèi)容,解析成一個(gè) AST。然后我們使用 ast.dump 將其導(dǎo)出并打印。
注意:indent 這個(gè)參數(shù)是 Python 3.9 以后才有的,如果版本低的話,可以去掉,只會(huì)影響最后輸出的格式。

python的簡(jiǎn)單四則運(yùn)算語(yǔ)法樹(shù)可視化如何實(shí)現(xiàn)

好了,就是這么簡(jiǎn)單。我們已經(jīng)做到了,因?yàn)檫@個(gè)庫(kù)的功能很強(qiáng)大,但是這里只是用到一點(diǎn)點(diǎn)而已。其實(shí)這里已經(jīng)可以看出基本的結(jié)構(gòu)了,不過(guò)我的目的是生成這棵樹(shù)的 JSON 表示。我想要使用上面的 Python 繪圖庫(kù)把它繪制出來(lái),它所支持的輸入是 JSON,并且它的格式為:

{
	"name": "A",
	"children": [
		"name": "B",
		"children": []
	]
}
粗糙的遍歷方法
"""
Python's AST
利用 Python 的 ast 模塊來(lái)解析表達(dá)式(簡(jiǎn)單的二元運(yùn)算),
然后通過(guò)遍歷語(yǔ)法樹(shù)來(lái)生成 JSON 表示,再使用 PYthon 的庫(kù)來(lái)
將其可視化。這個(gè)程序的目的是為了驗(yàn)證自己寫(xiě)的簡(jiǎn)易解析器是否正確。
"""

import ast
import json


# 操作類(lèi)型和操作符映射的字典
OPERATORS = {
    ast.Add: "+",
    ast.Sub: "-",
    ast.Mult: "*",
    ast.Div: "/"
}


def generate(tree: ast.Module):
    """
    generate expression AST's representation of JSON
    """
    if not tree:
        raise Exception("Emtpy AST tree!")
    if tree.__class__ == ast.Module:
        print(json.dumps({
            "name": "Expr",
            "children": [DFS(tree.body[0].value)]  # type: ignore
        }, indent=4))


def DFS(node):
    """
    DFS AST
    """
    if not node:
        return {}

    if node.__class__ == ast.BinOp:
        return {
            "name": "BinOp",
            "children": [
                {
                    "name": "left",
                    "children": [
                        DFS(node.left)
                    ]
                },
                DFS(node.op),
                {
                    "name": "left",
                    "children": [
                        DFS(node.right)
                    ]
                }
            ]
        }

    if node.__class__ == ast.Constant:
        return {
            "name": "NUMBER",
            "children": [
                {
                    "name": str(node.value)  # Python 的繪圖庫(kù),必須是字符串才能正常顯示
                }
            ]
        }

    if node.__class__ in [ast.Add, ast.Sub, ast.Mult, ast.Div]:
        return {
            "name": "Op",
            "children": [
                {
                    "name": OPERATORS[node.__class__]
                }
            ]
        }

    # 這里我只處理 加減乘除和數(shù)字類(lèi)型的運(yùn)行
    raise Exception("There is not support extra type.")


if __name__ == "__main__":
    ast_tree = ast.parse("1+2+3+4+5")
    print(ast.dump(ast_tree, indent=4))
    generate(ast_tree)

運(yùn)行結(jié)果:
我這里會(huì)輸出兩個(gè)東西,一個(gè)是 AST 的 dump;另一個(gè)是 AST 的 JSON 表示(邏輯結(jié)構(gòu)的 JSON 表示,不是對(duì)象的 JSON 表示)。

python的簡(jiǎn)單四則運(yùn)算語(yǔ)法樹(shù)可視化如何實(shí)現(xiàn)

渲染顯示

把打印出來(lái)的 JSON 字符串復(fù)制進(jìn)文件,命名為 data.json。我感覺(jué)直接輸出到控制臺(tái)蠻有意思的,我喜歡直接看到它的結(jié)果。
執(zhí)行如下命令:pytm-cli -d TB -i data.json -o demo.html
在瀏覽器打開(kāi) demo.html 即可看到效果了。

python的簡(jiǎn)單四則運(yùn)算語(yǔ)法樹(shù)可視化如何實(shí)現(xiàn)

主流的遍歷方法

上面這種遍歷方法雖然便于理解,但是難以擴(kuò)展。AST 通常是通過(guò) 訪問(wèn)者模式 進(jìn)行遍歷的,而且 ast 庫(kù)也提供了幾種遍歷方法。
因?yàn)檫@里只需要遍歷來(lái)生成 JSON,并不需要修改AST本身,所以我們只看下面這兩種即可。顯然第一種是不能用的,原因已經(jīng)用藍(lán)色標(biāo)記出來(lái)了。它自己說(shuō)了如果你不關(guān)心上下文,因?yàn)樯?JSON 實(shí)際上是需要關(guān)注這個(gè)的。所以,我選擇下面的 ast.NodeVisitor。使用它也很簡(jiǎn)單,繼承這個(gè)類(lèi),然后對(duì)不同的節(jié)點(diǎn)寫(xiě)不同的處理邏輯就行了(這樣把不同節(jié)點(diǎn)的邏輯分開(kāi)了,降低了代碼的耦合性)。

python的簡(jiǎn)單四則運(yùn)算語(yǔ)法樹(shù)可視化如何實(shí)現(xiàn)

完整代碼
"""
Python's AST
利用 Python 的 ast 模塊來(lái)解析表達(dá)式(簡(jiǎn)單的二元運(yùn)算),
然后通過(guò)遍歷語(yǔ)法樹(shù)來(lái)生成 JSON 表示,再使用 PYthon 的庫(kù)來(lái)
將其可視化。這個(gè)程序的目的是為了驗(yàn)證自己寫(xiě)的簡(jiǎn)易解析器是否正確。
"""

import ast
import json


# 操作類(lèi)型和操作符映射的字典
OPERATORS = {
    ast.Add: "+",
    ast.Sub: "-",
    ast.Mult: "*",
    ast.Div: "/"
}

class JSONVisitor(ast.NodeVisitor):
    """
    JSON visitor: Traversal AST and generate JSON representation
    """

    def visit_Module(self, node):
        module = {
            "name": "Module",
            "children": []
        }
        for sub_node in node.body:
            module["children"].append(self.visit(sub_node))

        return module

    def visit_Expr(self, node):
        return {
            "name": "Expr",
            "children": [
                self.visit(node.value)
            ]
        }

    def visit_BinOp(self, node):
        return {
            "name": "BinOp",
            "children": [
                {
                    "name": "left",
                    "children": [
                        self.visit(node.left)
                    ]
                },
                self.visit(node.op),
                {
                    "name": "right",
                    "children": [
                        self.visit(node.right)
                    ]
                }
            ]
        }

    def visit_Constant(self, node):
        return {
            "name": "NUMBER",
            "children": [{
                "name": str(node.value)  # # Python 的繪圖庫(kù),必須是字符串才能正常顯示
            }]
        }

    def visit_Add(self, node):
        return self.__visit(node)

    def visit_Sub(self, node):
        return self.__visit(node)

    def visit_Mult(self, node):
        return self.__visit(node)

    def visit_Div(self, node):
        return self.__visit(node)

    def __visit(self, node):
        return {
            "name": "Op",
            "children": [{
                "name": OPERATORS[node.__class__]
            }]
        }


if __name__ == "__main__":
    ast_tree = ast.parse("1+2+3+4+5")
    visitor = JSONVisitor()
    json_str = visitor.visit(ast_tree)
    print(json.dumps(json_str, indent=4))

前面那個(gè)粗糙版本是直接從 Expr 開(kāi)始的,這個(gè)優(yōu)雅點(diǎn)的版本,我就把 Module 節(jié)點(diǎn)也添加進(jìn)去了。

python的簡(jiǎn)單四則運(yùn)算語(yǔ)法樹(shù)可視化如何實(shí)現(xiàn)

“python的簡(jiǎn)單四則運(yùn)算語(yǔ)法樹(shù)可視化如何實(shí)現(xiàn)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI