在遥远的Python王国里,有一个非常热爱编程的少年。他的父母想让他报班。问了***的朋友圈,发现大家推荐的都是同一个老师,人称季老师。于是他的父母毫不犹豫地交了一大笔学费,每周六下午都让孩子自习。少年学习非常刻苦,很快学会了Python语法、工具和框架。老师仿佛看到了一块可以雕琢的美玉,无所不授,告诉他不仅要正确编写代码,还要让代码美观、优雅、可读、可维护。少年学习了单元测试、TDD、重构,努力让自己的代码达到老师要求的标准。他还在自己的墙上贴了《Python之禅》,时常对照自己的代码,从不敢违背。Python之禅,作者TimPeters美丽胜于丑陋。显式优于隐式。简单胜于复杂。复杂总比复杂好。扁平比嵌套好。稀疏比密集好。可读性很重要。……三年后,男孩以为自己成为了Python高手,直到有一天,老师给他布置了一个很大的作业,其实是一个大项目,业务非常复杂。少年彻夜编程,却悲惨地发现,无论他怎么努力,他的代码都是乱七八糟的,毫无美感,写的类和模块混杂在一起。于是他只好向老师请教:“老师,我的Python和Flask框架都已经很熟悉了,为什么我做不完这个项目呢?”老师说:“儿子,原来你只需要引入框架的类,写一点点代码就够了,现在你需要自己设计类,自己做抽象!”“怎么设计?”“送给老师一本古书,《设计模式》,你回去好好看看吧。”小伙子捡到宝了,只好睡觉忘了研究这本20多年前出版的泛黄古书,而且还是用C++来描述的。他一头雾水,似懂非懂,又似不懂,只好再请教老师。这次,老师又给了他一本书。男孩《Head First 设计模式》打开一看,这本书是用Java写的,于是又一头扎进了Java语言中。这本书比较通俗易懂,小伙子读的很开心。最后,他满怀信心地用Python开始了那个大项目。他用Python语言实现设计模式,解决了一些设计问题,但总感觉哪里不对。跟Java和C++比起来,他觉得怪怪的。此外,他还感受到了动态语言的不适。每次他想重构,他总是不敢去做。他把自己的困惑告诉了老师。老师笑着说:“我在Java王国的时候,总有人说‘动态很酷,重构火葬场’,现在你懂了!”“Java能避免这个问题吗?”《Java是一门静态语言,变量类型不能改变,对重构的支持很好,有没有兴趣看看?框架有很多,比如Spring,SpringBoot,MyBatis,Dubbo,Netty,非常繁荣和发达。”少年何向往,老师便给他写了一张纸条,告诉他,等他来到爪哇王国,找到了IO大臣,一切都会一帆风顺。少年告别老师,奔向爪哇帝国。老师整了整衣裳,看向东方爪哇帝国的方向,郑重鞠躬三拜:“五年了,IO大人,不负重托,我已经忽悠了另一个人去做Java!”原来老师是Gisen!IO部长派来传播Java文化和价值观的传教士,入境后不幸被发现,被关押在Python王国,请看吉森的故事《Java帝国对Python的渗透能成功吗?》Python没有界面?蟒王接到边境报告,说最近有很多年轻人涌入爪哇王国,蟒王大怒,下令严查.查了一下,所有的线索都指向致一人:吉森。这一天,蟒蛇特使带着士兵们来到了吉森的住处,原来他又在忽悠年轻人了。特使怒笑:“你学了个半生不熟的蟒蛇,还敢骗人,真是可笑。”季森见自己的阴谋被识破,不动声色:“大人误会了,我教的才是正宗的。面向对象设计和设计模式,这种设计模式用Python实现起来很别扭,推荐他们学习一下爪哇。”“废话,为什么用Python写设计模式这么别扭?由于Java语法有限,表达能力比较弱。对于某些问题,我们不得不使用笨拙的设计模式来解决它们。我们的Python可能会在语法层面解决问题!”“那你说说,设计模式的原则是什么?”Gieson问道。“1.面向接口的编程,而不是面向实现的编程。2.更喜欢组合而不是继承。”这对特使来说很难。“没有Python接口,如何针对接口编程?你以为这里的接口就是你的Java。界面!你忘了Python的DuckTyping了吗?”classDuck:deffly(self):打印(“Duckflying”)lift_off(plane)"看,Duck和Airplane都没有实现你所谓的接口,但是都可以调用fly()方法,这不就是面向接口的编程吗?非要打个比方,这个fly就是一个自动化的界面。”吉森还真没想到这一层。至于第二个原则,先用组合而不是继承,这在任何面向对象的语言中都可以实现。他叹了口气,不再问了。Adapter模式使者继续说:“DuckTyping很强大,你不是说设计模式吗,在DuckTyping面前,很多设计模式纯属画蛇添足。举个例子,Adapter模式。假设客户端有这样一段代码,可以将一段日志写入文件。"deflog(file,msg):file.write('[{}]-{}'.format(datetime.now(),msg))"现在有一个新的需求,要把日志写入数据库,而数据库没有write方法,怎么办呢,那就写一个Adapter吧。"classDBAdapter:def__init__(self,db):self.db=dbdefwrite(self,msg):self.db.insert(msg)"注意这个DBAdapter不需要实现任何接口(我在Python中没有接口),它只是一个单独的类,只需要有一个写方法。"db_adapter=DBAdapter(db)log(db_adapter,"sev1erroroccurred")确实很简单,只要有write方法,不管你是什么对象,都可以调用,典型的DuckTyping。既然Adapter可以这么写这个,Proxy模式也是类似的,只要你的Proxy类有和被代理类一样的方法,就可以给客户使用。但是这种方法的缺点是不知道参数类型很难重构log方法的单例模式Gisen想到了另外一个问题,继续挑战特使:“Python连private关键字都没有,如何隐藏类的构造函数,如何实现单例?”特使envoy不屑的说道:“忘掉你的Java想想吧,用Python写单例有很多种方式,我给你展示一种更Pythonic的方式,用模块的方式来实现。"#singleton.pyclassSingleton:def__init__(self):self.name="i'msingleton"instance=Singleton()delSingleton#删除构造函数使用Singleton:importsingletonprint(singleton.instance.name)#i'msingletoninstance=Singleton()#NameError:name'Singleton'isnotdefinedGiseon还真没想到这种写法,用Python模块来隐藏信息,不是每个设计模式都能做到Visitor模式吗?Giseon心想,脑子里出现了一个难以理解的问题模式:访客,我努力学习它。吉森道:“那你说说,如何使用PythonforVisitor的特性?”"classTreeNode:def__init__(self,data):self.data=dataself.left=Noneself.right=Nonedefaccept(self,visitor):ifself.leftisnotNone:self.left.accept(visitor)visitor.visit(self)ifself.rightisnotNone:self.right.accept(visitor)classPrintVisitor:defvisit(self,node):print(node.data)root=TreeNode('1')root.left=TreeNode('2')root.right=TreeNode('3')visitor=PrintVisitor()root.accept(visitor)#Output2,1,3Gison说:“对啊,Visitor模式不就是这么写的吗?”“我就说你刚学了一点点Python嘛,Visitor的本质就是结构和操作分离,在Python中使用generator可以更优雅的实现。”classTreeNode:def__iter__(self):returnsself.__generator()def__generator(self):ifself.leftisnotNone:yieldfromiter(self.left)yieldfromself.dataifself.rightisnotNone:yieldfromiter(self.right)root=TreeNode('1')root.left=TreeNode('2')root.right=TreeNode('3')foreleinroot:print(ele)不得不承认,这种方式使用起来更加简洁,同时达到了结构和操作分离的目的。特使说:“你看,Python在语言层面提供了一些模式的支持,所以很多设计模式在我看来Python很笨拙,这里不提倡。当然,原理还是要掌握的面向对象设计的SOLID和设计模式的思想,发现变化,封装变化,从而写出优雅的程序。”吉森叹了口气,觉得自己学不好,于是停止反抗,结果被抓了起来。最后,蟒蛇王国审判了本该判处死刑的吉森,爪哇帝国却重兵压境,要求释放他,否则就会开战。Giseon被送回爪哇王国,成为人们心目中的英雄。回国后,他仔细比较了Java和Python,并在Java虚拟机上实现了Python语言!为了表彰他的英雄事迹,国王将这种语言命名为Jython。【本文为专栏作家“刘欣”原创稿件,转载请通过作者微信获得授权公众号编码】点此查看更多好文由这位作者
