<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## 問題 你要處理由大量不同類型的對象組成的復雜數據結構,每一個對象都需要需要進行不同的處理。比如,遍歷一個樹形結構,然后根據每個節點的相應狀態執行不同的操作。 ## 解決方案 這里遇到的問題在編程領域中是很普遍的,有時候會構建一個由大量不同對象組成的數據結構。假設你要寫一個表示數學表達式的程序,那么你可能需要定義如下的類: class Node: pass class UnaryOperator(Node): def __init__(self, operand): self.operand = operand class BinaryOperator(Node): def __init__(self, left, right): self.left = left self.right = right class Add(BinaryOperator): pass class Sub(BinaryOperator): pass class Mul(BinaryOperator): pass class Div(BinaryOperator): pass class Negate(UnaryOperator): pass class Number(Node): def __init__(self, value): self.value = value 然后利用這些類構建嵌套數據結構,如下所示: # Representation of 1 + 2 * (3 - 4) / 5 t1 = 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()` )。 可以參照8.22小節,利用生成器或迭代器來實現非遞歸遍歷算法。 在跟解析和編譯相關的編程中使用訪問者模式是非常常見的。Python本身的 `ast` 模塊值的關注下,可以去看看源碼。9.24小節演示了一個利用 `ast` 模塊來處理Python源代碼的例子。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看