最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python 如何實(shí)現(xiàn)訪問(wèn)者模式

 更新時(shí)間:2020年07月28日 11:44:01   作者:看云  
這篇文章主要介紹了Python 如何實(shí)現(xiàn)訪問(wèn)者模式,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下

問(wèn)題

你要處理由大量不同類(lèi)型的對(duì)象組成的復(fù)雜數(shù)據(jù)結(jié)構(gòu),每一個(gè)對(duì)象都需要需要進(jìn)行不同的處理。比如,遍歷一個(gè)樹(shù)形結(jié)構(gòu),然后根據(jù)每個(gè)節(jié)點(diǎn)的相應(yīng)狀態(tài)執(zhí)行不同的操作。

解決方案

這里遇到的問(wèn)題在編程領(lǐng)域中是很普遍的,有時(shí)候會(huì)構(gòu)建一個(gè)由大量不同對(duì)象組成的數(shù)據(jù)結(jié)構(gòu)。假設(shè)你要寫(xiě)一個(gè)表示數(shù)學(xué)表達(dá)式的程序,那么你可能需要定義如下的類(lèi):

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

然后利用這些類(lèi)構(gòu)建嵌套數(shù)據(jù)結(jié)構(gòu),如下所示:

# 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)

這樣做的問(wèn)題是對(duì)于每個(gè)表達(dá)式,每次都要重新定義一遍,有沒(méi)有一種更通用的方式讓它支持所有的數(shù)字和操作符呢。這里我們使用訪問(wèn)者模式可以達(dá)到這樣的目的:

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__))

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

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
>>>

作為一個(gè)不同的例子,下面定義一個(gè)類(lèi)在一個(gè)棧上面將一個(gè)表達(dá)式轉(zhuǎn)換成多個(gè)操作序列:

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',)]
>>>

討論

剛開(kāi)始的時(shí)候你可能會(huì)寫(xiě)大量的if/else語(yǔ)句來(lái)實(shí)現(xiàn),這里訪問(wèn)者模式的好處就是通過(guò) getattr() 來(lái)獲取相應(yīng)的方法,并利用遞歸來(lái)遍歷所有的節(jié)點(diǎn):

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

還有一點(diǎn)需要指出的是,這種技術(shù)也是實(shí)現(xiàn)其他語(yǔ)言中switch或case語(yǔ)句的方式。比如,如果你正在寫(xiě)一個(gè)HTTP框架,你可能會(huì)寫(xiě)這樣一個(gè)請(qǐng)求分發(fā)的控制器:

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

訪問(wèn)者模式一個(gè)缺點(diǎn)就是它嚴(yán)重依賴(lài)遞歸,如果數(shù)據(jù)結(jié)構(gòu)嵌套層次太深可能會(huì)有問(wèn)題,有時(shí)候會(huì)超過(guò)Python的遞歸深度限制(參考 sys.getrecursionlimit() )。

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

以上就是Python 如何實(shí)現(xiàn)訪問(wèn)者模式的詳細(xì)內(nèi)容,更多關(guān)于Python 訪問(wèn)者模式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 教你如何用pycharm安裝pyqt5及其相關(guān)配置

    教你如何用pycharm安裝pyqt5及其相關(guān)配置

    這篇文章主要介紹了教你如何用pycharm安裝pyqt5及其相關(guān)配置,首先通過(guò)單獨(dú)創(chuàng)建一個(gè)文件夾來(lái)專(zhuān)門(mén)存放pyqt5的代碼并建立虛擬環(huán)境展開(kāi)文章敘述,需要的小伙伴可以參考一下
    2022-04-04
  • python實(shí)現(xiàn)斷點(diǎn)調(diào)試的方法

    python實(shí)現(xiàn)斷點(diǎn)調(diào)試的方法

    本文主要介紹了python實(shí)現(xiàn)斷點(diǎn)調(diào)試的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • Python實(shí)現(xiàn)微信好友的數(shù)據(jù)分析

    Python實(shí)現(xiàn)微信好友的數(shù)據(jù)分析

    這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)微信好友的數(shù)據(jù)分析,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • Python實(shí)現(xiàn)子類(lèi)調(diào)用父類(lèi)的方法

    Python實(shí)現(xiàn)子類(lèi)調(diào)用父類(lèi)的方法

    這篇文章主要介紹了Python實(shí)現(xiàn)子類(lèi)調(diào)用父類(lèi)的方法,解決子類(lèi)覆蓋父類(lèi)初始化方法而出現(xiàn)的不確定問(wèn)題,可通過(guò)調(diào)用超類(lèi)構(gòu)造方法的未綁定版本或者使用super函數(shù)來(lái)解決,需要的朋友可以參考下
    2014-11-11
  • 解決pyinstaller打包exe文件出現(xiàn)命令窗口一閃而過(guò)的問(wèn)題

    解決pyinstaller打包exe文件出現(xiàn)命令窗口一閃而過(guò)的問(wèn)題

    今天小編就為大家分享一篇解決pyinstaller打包exe文件出現(xiàn)命令窗口一閃而過(guò)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-10-10
  • Pytorch常用的維度轉(zhuǎn)換方法

    Pytorch常用的維度轉(zhuǎn)換方法

    在PyTorch中,我們經(jīng)常需要處理多維數(shù)據(jù),如張量tensors,這篇文章主要介紹了一些Pytorch常用的維度轉(zhuǎn)換方法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-03-03
  • Python新年炫酷煙花秀代碼

    Python新年炫酷煙花秀代碼

    大家好,本篇文章主要講的是Python新年炫酷煙花秀代碼,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2022-01-01
  • Python pandas軸旋轉(zhuǎn)stack和unstack的使用說(shuō)明

    Python pandas軸旋轉(zhuǎn)stack和unstack的使用說(shuō)明

    這篇文章主要介紹了Python pandas軸旋轉(zhuǎn)stack和unstack的使用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-03-03
  • Numpy如何檢查數(shù)組全為零的幾種方法

    Numpy如何檢查數(shù)組全為零的幾種方法

    本文主要介紹了Numpy如何檢查數(shù)組全為零的幾種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • python中以函數(shù)作為參數(shù)(回調(diào)函數(shù))的實(shí)現(xiàn)方法

    python中以函數(shù)作為參數(shù)(回調(diào)函數(shù))的實(shí)現(xiàn)方法

    這篇文章主要介紹了python中以函數(shù)作為參數(shù)(回調(diào)函數(shù))的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01

最新評(píng)論

布尔津县| 兴海县| 凤庆县| 六盘水市| 安顺市| 婺源县| 长宁县| 那坡县| 瑞金市| 汤阴县| 廉江市| 上虞市| 海丰县| 崇阳县| 余干县| 兰西县| 道孚县| 辉县市| 本溪| 拉萨市| 大名县| 饶阳县| 武鸣县| 海兴县| 东丽区| 平昌县| 嘉义县| 崇州市| 英超| 卢龙县| 巴青县| 裕民县| 苏州市| 五大连池市| 泰来县| 含山县| 榆树市| 丹阳市| 正镶白旗| 罗江县| 江安县|