电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

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

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

問題

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

解決方案

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

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

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

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

這樣做的問題是對(duì)于每個(gè)表達(dá)式,每次都要重新定義一遍,有沒有一種更通用的方式讓它支持所有的數(shù)字和操作符呢。這里我們使用訪問者模式可以達(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è)類,可以定義一個(gè)類繼承它并且實(shí)現(xiàn)各種 visit_Name() 方法,其中Name是node類型。例如,如果你想求表達(dá)式的值,可以這樣寫:

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è)類在一個(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’,)]>>>

討論

剛開始的時(shí)候你可能會(huì)寫大量的if/else語(yǔ)句來(lái)實(shí)現(xiàn),這里訪問者模式的好處就是通過 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ǔ)句的方式。比如,如果你正在寫一個(gè)HTTP框架,你可能會(huì)寫這樣一個(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

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

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

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

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 杭州成人高考_浙江省成人高考网上报名 | 硫酸亚铁-聚合硫酸铁-除氟除磷剂-复合碳源-污水处理药剂厂家—长隆科技 | 河南档案架,档案密集架,手动密集架,河南密集架批发/报价 | 高压油管,液压接头,液压附件-烟台市正诚液压附件 | 德国进口电锅炉_商用电热水器_壁挂炉_电采暖器_电热锅炉[德国宝] | 冷凝锅炉_燃气锅炉_工业燃气锅炉改造厂家-北京科诺锅炉 | 南京种植牙医院【官方挂号】_南京治疗种植牙医院那个好_南京看种植牙哪里好_南京茀莱堡口腔医院 尼龙PA610树脂,尼龙PA612树脂,尼龙PA1010树脂,透明尼龙-谷骐科技【官网】 | 深圳市索富通实业有限公司-可燃气体报警器 | 可燃气体探测器 | 气体检测仪 | 小程序开发公司-小程序制作-微信小程序开发-小程序定制-咏熠软件 | 成都茶楼装修公司 - 会所设计/KTV装修 - 成都朗煜装饰公司 | TPE_TPE热塑性弹性体_TPE原料价格_TPE材料厂家-惠州市中塑王塑胶制品公司- 中塑王塑胶制品有限公司 | arch电源_SINPRO_开关电源_模块电源_医疗电源-东佑源 | 常州翔天实验仪器厂-恒温振荡器-台式恒温振荡器-微量血液离心机 恒温恒湿箱(药品/保健品/食品/半导体/细菌)-兰贝石(北京)科技有限公司 | 不锈钢发酵罐_水果酒发酵罐_谷物发酵罐_山东誉诚不锈钢制品有限公司 | 河南中整光饰机械有限公司-抛光机,去毛刺抛光机,精密镜面抛光机,全自动抛光机械设备 | 脱硝喷枪-氨水喷枪-尿素喷枪-河北思凯淋环保科技有限公司 | 臭氧发生器_臭氧消毒机 - 【同林品牌 实力厂家】 | 固诺家居-全屋定制十大品牌_整体衣柜木门橱柜招商加盟 | 密封无忧网 _ 专业的密封产品行业信息网 | 数码听觉统合训练系统-儿童感觉-早期言语评估与训练系统-北京鑫泰盛世科技发展有限公司 | 制丸机,小型中药制丸机,全自动制丸机价格-甘肃恒跃制药设备有限公司 | 商标转让-商标注册-商标查询-软著专利服务平台 - 赣江万网 | 吨袋包装机|吨包秤|吨包机|集装袋包装机-烟台华恩科技 | 蜘蛛车-高空作业平台-升降机-高空作业车租赁-臂式伸缩臂叉装车-登高车出租厂家 - 普雷斯特机械设备(北京)有限公司 | 无菌实验室规划装修设计-一体化实验室承包-北京洁净净化工程建设施工-北京航天科恩实验室装备工程技术有限公司 | HDPE土工膜,复合土工膜,防渗膜价格,土工膜厂家-山东新路通工程材料有限公司 | 精密机械零件加工_CNC加工_精密加工_数控车床加工_精密机械加工_机械零部件加工厂 | 座椅式升降机_无障碍升降平台_残疾人升降平台-南京明顺机械设备有限公司 | 旋片真空泵_真空泵_水环真空泵_真空机组-深圳恒才机电设备有限公司 | 深圳网站建设-高端企业网站开发-定制网页设计制作公司 | 郑州大巴车出租|中巴车租赁|旅游大巴租车|包车|郑州旅游大巴车租赁有限公司 | 长沙发电机-湖南发电机-柴油发电机供应厂家-长沙明邦智能科技 | 档案密集柜_手动密集柜_智能密集柜_内蒙古档案密集柜-盛隆柜业内蒙古密集柜直销中心 | DNA亲子鉴定_DNA基因检测中心官方预约平台-严选好基因网 | 国标白水泥,高标号白水泥,白水泥厂家-淄博华雪建材有限公司 | 福建珂朗雅装饰材料有限公司「官方网站」 | vr安全体验馆|交通安全|工地安全|禁毒|消防|安全教育体验馆|安全体验教室-贝森德(深圳)科技 | 数控走心机-双主轴走心机厂家-南京建克 | [官网]叛逆孩子管教_戒网瘾学校_全封闭问题青少年素质教育_新起点青少年特训学校 | 锻造液压机,粉末冶金,拉伸,坩埚成型液压机定制生产厂家-山东威力重工官方网站 | 球形钽粉_球形钨粉_纳米粉末_难熔金属粉末-广东银纳官网 |