成人视屏在线观看-国产99精品-国产精品1区2区-欧美一级在线观看-国产一区二区日韩-色九九九

您的位置:首頁技術文章
文章詳情頁

Python 如何實現訪問者模式

瀏覽:85日期:2022-07-16 09:36:42

問題

你要處理由大量不同類型的對象組成的復雜數據結構,每一個對象都需要需要進行不同的處理。比如,遍歷一個樹形結構,然后根據每個節點的相應狀態執行不同的操作。

解決方案

這里遇到的問題在編程領域中是很普遍的,有時候會構建一個由大量不同對象組成的數據結構。假設你要寫一個表示數學表達式的程序,那么你可能需要定義如下的類:

class Node: passclass UnaryOperator(Node): def __init__(self, operand): self.operand = operandclass BinaryOperator(Node): def __init__(self, left, right): self.left = left self.right = rightclass Add(BinaryOperator): passclass Sub(BinaryOperator): passclass Mul(BinaryOperator): passclass Div(BinaryOperator): passclass Negate(UnaryOperator): passclass Number(Node): def __init__(self, value): self.value = value

然后利用這些類構建嵌套數據結構,如下所示:

# Representation of 1 + 2 * (3 - 4) / 5t1 = Sub(Number(3), Number(4))t2 = Mul(Number(2), t1)t3 = Div(t2, Number(5))t4 = Add(Number(1), t3)

這樣做的問題是對于每個表達式,每次都要重新定義一遍,有沒有一種更通用的方式讓它支持所有的數字和操作符呢。這里我們使用訪問者模式可以達到這樣的目的:

class NodeVisitor: def visit(self, node): methname = ’visit_’ + type(node).__name__ meth = getattr(self, methname, None) if meth is None: meth = self.generic_visit return meth(node) def generic_visit(self, node): raise RuntimeError(’No {} method’.format(’visit_’ + type(node).__name__))

為了使用這個類,可以定義一個類繼承它并且實現各種 visit_Name() 方法,其中Name是node類型。例如,如果你想求表達式的值,可以這樣寫:

class Evaluator(NodeVisitor): def visit_Number(self, node): return node.value def visit_Add(self, node): return self.visit(node.left) + self.visit(node.right) def visit_Sub(self, node): return self.visit(node.left) - self.visit(node.right) def visit_Mul(self, node): return self.visit(node.left) * self.visit(node.right) def visit_Div(self, node): return self.visit(node.left) / self.visit(node.right) def visit_Negate(self, node): return -node.operand

使用示例:

>>> e = Evaluator()>>> e.visit(t4)0.6>>>

作為一個不同的例子,下面定義一個類在一個棧上面將一個表達式轉換成多個操作序列:

class StackCode(NodeVisitor): def generate_code(self, node): self.instructions = [] self.visit(node) return self.instructions def visit_Number(self, node): self.instructions.append((’PUSH’, node.value)) def binop(self, node, instruction): self.visit(node.left) self.visit(node.right) self.instructions.append((instruction,)) def visit_Add(self, node): self.binop(node, ’ADD’) def visit_Sub(self, node): self.binop(node, ’SUB’) def visit_Mul(self, node): self.binop(node, ’MUL’) def visit_Div(self, node): self.binop(node, ’DIV’) def unaryop(self, node, instruction): self.visit(node.operand) self.instructions.append((instruction,)) def visit_Negate(self, node): self.unaryop(node, ’NEG’)

使用示例:

>>> s = StackCode()>>> s.generate_code(t4)[(’PUSH’, 1), (’PUSH’, 2), (’PUSH’, 3), (’PUSH’, 4), (’SUB’,),(’MUL’,), (’PUSH’, 5), (’DIV’,), (’ADD’,)]>>>

討論

剛開始的時候你可能會寫大量的if/else語句來實現,這里訪問者模式的好處就是通過 getattr() 來獲取相應的方法,并利用遞歸來遍歷所有的節點:

def binop(self, node, instruction): self.visit(node.left) self.visit(node.right) self.instructions.append((instruction,))

還有一點需要指出的是,這種技術也是實現其他語言中switch或case語句的方式。比如,如果你正在寫一個HTTP框架,你可能會寫這樣一個請求分發的控制器:

class HTTPHandler: def handle(self, request): methname = ’do_’ + request.request_method getattr(self, methname)(request) def do_GET(self, request): pass def do_POST(self, request): pass def do_HEAD(self, request): pass

訪問者模式一個缺點就是它嚴重依賴遞歸,如果數據結構嵌套層次太深可能會有問題,有時候會超過Python的遞歸深度限制(參考 sys.getrecursionlimit() )。

在跟解析和編譯相關的編程中使用訪問者模式是非常常見的。Python本身的 ast 模塊值的關注下,可以去看看源碼。

以上就是Python 如何實現訪問者模式的詳細內容,更多關于Python 訪問者模式的資料請關注好吧啦網其它相關文章!

標簽: Python 編程
相關文章:
主站蜘蛛池模板: 国产真实乱子伦精品视 | 欧美一区二区精品系列在线观看 | 国产第三区 | 在线欧美精品二区三区 | 美女wc| 97精品国产91久久久久久 | 二级黄的全免费视频 | 国产第一亚洲 | 国产99视频精品一区 | 久草视频在线资源站 | a级网站在线观看 | 日韩黄色视屏 | 视频在线亚洲 | 国产高清a毛片在线看 | 国产成人精品久久二区二区 | 日本二级毛片免费 | 一级做a爰 | 一级特级欧美a毛片免费 | 亚洲人的天堂男人爽爽爽 | 日本特级淫片免费看 | 免费高清国产 | 精品国产香蕉伊思人在线 | 美女张开腿让男人桶爽动漫视频 | 国产精品免费综合一区视频 | 亚洲小视频在线播放 | 黄网站在线播放视频免费观看 | 欧美一级带 | 国产欧美在线视频 | 在线观看免费国产 | 亚洲黄色免费网址 | 精品中文字幕一区在线 | 黄色wwwxxx| 在线日本视频 | 福利视频99| 日本成a人片在线观看网址 日本成年人视频网站 | 亚洲品质自拍视频 | 性色网址| 国产做爰一区二区 | 麻豆国产96在线 | 中国 | 在线黄色影院 | 欧美成人久久久免费播放 |