内容简介:在遥远的Python王国,有一位少年,非常热爱编程,他的父母想给他报一个班,问了万能的朋友圈以后,发现大家都推荐同一个老师,人称吉先生。于是他的父母毫不犹豫就交了一笔不菲的学费,每周六日下午让孩子去学习。少年学习非常刻苦,很快就学会了Python语法、工具和框架。
在遥远的 Python 王国,有一位少年,非常热爱编程,他的父母想给他报一个班,问了万能的朋友圈以后,发现大家都推荐同一个老师,人称吉先生。
于是他的父母毫不犹豫就交了一笔不菲的学费,每周六日下午让孩子去学习。
少年学习非常刻苦,很快就学会了Python语法、 工具 和框架。
老师像是见到了可以雕刻的美玉, 倾囊相授,告诉他不仅要把代码写对,还要让代码漂亮、优雅、可读、可维护。
少年又学会了单元测试,TDD,重构,努力让自己的代码达到老师所要求的标准。
他还把“Python 之禅”贴在了自己的墙上,经常对照自己的代码,从来都不敢违反。
- The Zen of Python, by Tim Peters
- Beautiful is better than ugly.
- Explicit is better than implicit.
- Simple is better than complex.
- Complex is better than complicated.
- Flat is better than nested.
- Sparse is better than dense.
- Readability counts.
- ......
三年以后,少年以为自己成为了Python的大师,直到有一天,老师给他布置了一个大作业,其实是个大项目,业务非常复杂。
少年通宵达旦地编程,可他悲惨地发现,无论他怎么努力,他的代码都是乱糟糟的,没有美感,他所写出的类,模块混成了一团。
于是他只好去请教老师: “老师,我的Python和Flask框架已经用得滚瓜烂熟了,为什么完成不了这个项目呢?”
老师说:“孩子,原来你只需要把框架的类给import进来,稍微写点儿代码就行了,现在你需要自己去设计类,自己去做出抽象了!”
“怎么设计呢?”
“为师送你一本古书,《设计模式》 ,你回去好好看看吧。”
少年如获至宝, 废寝忘食地去研究这本20多年前出的、泛黄的古书,还是用C++描述的。
他看得云里雾里,似乎明白,又似乎不明白,只好再去请教老师。
这一次,老师给了他另外一本书, 《Head First 设计模式》
少年翻开一看,这本书是用 Java 写的,于是又一头扎到了Java语言当中。
这本书比较通俗易懂,少年看得大呼过瘾。
终于,他信心十足地用Python开始那个大项目了。
他用Python语言实现设计模式,解决一些设计问题,可是总觉得不对劲,和Java , C++相比,感觉怪怪的。
另外他感觉到了动态语言的不爽之处,每次想重构的时候,总是不敢下手,他把困惑给老师说了。
老师笑道:“我在Java王国的时候,人们总是说‘动态一时爽,重构火葬场’, 现在你体会到了吧!”
“Java就能避免这个问题吗?”
“Java是一门静态语言,变量类型一旦确定就不能改变,对重构的支持非常好,你有没有兴趣去看看?那里有很多的框架,像Spring,Spring Boot,MyBatis, Dubbo, Netty,非常繁荣发达。”
少年心生向往,于是老师就给他写了个条子,告诉他说到了Java王国,找到IO大臣,一切事情都会畅通无阻。
少年辞别老师,奔向了Java帝国,老师整了整衣冠, 望着东方Java帝国的方向,庄严地拜了三拜:“五年了,IO大人,我没有辜负您的重托,又忽悠了一个人去做Java了!”
原来这位老师就是吉森! IO大臣派来传播Java文化和价值观的传教士,入境后不幸被识破,软禁在了Python王国。
吉森的故事请移步《Java帝国对Python的渗透能成功吗?》
Python没有接口?
Python国王收到边关的奏报,说是最近有不少年轻人奔向了Java王国,不知道是不是国内政策有变,导致人心浮动。
Python国王震怒,下令严查。 查来查去,所有的线索都指向了一个人:吉森。
这一天,Python特使带着士兵来到了吉森的住所,果然发现他又在忽悠年轻人了。
特使又气又笑:“你学了半吊子的Python,居然敢来蛊惑人心,实在是可笑。”
吉森看到自己的计谋已被识破,依然很镇静:“大人误会了,我教的就是正宗的面向对象的设计和 设计模式 啊,这设计模式用Python实现起来很别扭,我就推荐他们去学Java啊。”
“胡说,Python写设计模式怎么会很别扭? Java 由于语法所限,表达能力比较弱,对于一些问题,只好用笨拙的设计模式来解决,我们Python有可能在语法层面就解决问题了!”
“那你说说,设计模式的原则是什么?” 吉森问道。
“1. 面向接口编程,而不是面向实现编程。2. 优先使用组合而不是继承。” 这是难不住特使的。
“Python连接口都没有,怎么面向接口编程?” 吉森问道。
特使哈哈大笑:“说你是半吊子吧,你还不服,你以为这里的接口就是你们Java的interface啊!你忘了Python的Duck Typing了?”
class Duck: def fly(self): print("Duck flying") class Airplane: def fly(self): print("Airplane flying") def lift_off(entity): entity.fly() duck = Duck() plane = Airplane() lift_off(duck) lift_off(plane)
“看到没有, Duck和Airplane都没有实现你所谓的接口,但是都可以调用fly()方法,这难道不是面向接口编程, 如果你非要类比的话,这个fly就是一个自动化的接口啊。”
吉森确实没想到这一层,至于第二个原则,优先使用组合而不是继承,可以是每个面向对象的语言都可以实现的,他叹了口气,也就不问了。
Adapter模式
特使接着说:“Duck Typing非常强大,你不是提到了设计模式吗,在Duck Typing面前,很多设计模式纯属多此一举。我来给你举个例子,Adapter模式。假设客户端有这么一段代码,可以把一段日志写入文件当中。”
def log(file,msg): file.write('[{}] - {}'.format(datetime.now(), msg))
“现在来了新的需求,要把日志写入数据库, 而数据库并没有write 方法,怎么办? 那就写个Adapter吧。”
class DBAdapter: def __init__(self, db): self.db = db def write(self, msg): self.db.insert(msg)
“注意这个DBAdapter并不需要实现什么接口(我大Python也没有接口),就是一个单独的类,只需要有个write方法就可以了。”
db_adapter = DBAdapter(db) log(db_adapter, "sev1 error occurred")
确实是很简单,只要有write 方法, 不管你是任何对象,都可以进行调用, 典型的Duck Typing 。
既然Adapter可以这么写,那Proxy模式也是类似了,只要你的Proxy类和被代理的类的方法一样,那就可以被客户使用。
但是这种方法的弊端就是,不知道log方法的参数类型,想要重构可就难了。
单例模式
吉森又想到了一个问题,继续挑战特使:“Python连个private 关键字都没有,怎么隐藏一个类的构造函数,怎么去实现单例?”
特使不屑地说:“忘掉你那套Java思维吧,在Python中想写个singleton有很多办法,我给你展示一个比较Python的方式,用module的方式来实现。”
#singleton.py class Singleton: def __init__(self): self.name = "i'm singleton" instance = Singleton() del Singleton # 把构造函数删除
使用Singleton:
import singleton print(singleton.instance.name) # i'm singleton instance = Singleton() # NameError: name 'Singleton' is not defined
吉森确实没有想到这种写法,利用Python的module来实现信息的隐藏。
Visitor模式
不是每个设计模式都能这么干吧? 吉森心中暗想,他脑海中浮现了一个难于理解的模式:Visitor,自己当初为了学习它可是下了苦工。
吉森说:“那你说说,对于Visitor,怎么利用Python的特色?”
“我知道你心里想的是什么,无非就是想让我写一个类,然后在写个Visitor对它进行访问,是不是?”
class TreeNode: def __init__(self, data): self.data = data self.left = None self.right = None def accept(self, visitor): if self.left is not None: self.left.accept(visitor) visitor.visit(self) if self.right is not None: self.right.accept(visitor) class PrintVisitor: def visit(self,node): print(node.data) root = TreeNode('1') root.left = TreeNode('2') root.right = TreeNode('3') visitor = PrintVisitor() root.accept(visitor) #输出2, 1, 3
吉森说:“是啊, 难道Visitor模式不是这么写的吗? ”
"我就说你的Python只是学了点皮毛吧,Visitor的本质是在分离结构和操作, 在Python中使用generator可以更加优雅地实现。”
class TreeNode: def __iter__(self): return self.__generator() def __generator(self): if self.left is not None: yield from iter(self.left) yield from self.data if self.right is not None: yield from iter(self.right) root = TreeNode('1') root.left = TreeNode('2') root.right = TreeNode('3') for ele in root: print(ele)
不得不承认,这种方式使用起来更加简洁,同时达到了结构和操作进行分离的目的。
特使说道: “看到了吧,Python在语言层面对一些模式提供了支持,所以很多设计模式在我大Python看起来非常笨拙,我们这里并不提倡,当然我们还是要掌握面向对象设计的原则SOLID和设计模式的思想,发现变化并且封装变化,这样才能写出优雅的程序出来。”
吉森叹了一口气,感慨自己学艺不精,不再反抗,束手就擒。
尾声
Python王国审判了吉森,本来要判他死刑,但是Java帝国重兵压境,要求释放,否则就开战。
吉森被送回Java王国,成为了人们心目中的英雄,回家他仔细对比了Java和Python,在Java虚拟机上把Python语言给实现了!国王为了表彰他的英勇事迹,把这个语言叫做Jython。
【本文为51CTO专栏作者“刘欣”的原创稿件,转载请通过作者微信公众号coderising获取授权】
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Haskell函数式编程基础
Simon Thompson / 科学出版社 / 2013-7-1 / 129.00
《Haskell函数式编程基础(第3版)》是一本非常优秀的Haskell函数式程序设计的入门书,各章依次介绍函数式程序设计的基本概念、编译器和解释器、函数的各种定义方式、简单程序的构造、多态和高阶函数、诸如数组和列表的结构化数据、列表上的原始递归和推理、输入输出的控制处理、类型分类与检测方法、代数数据类型、抽象数据类型、惰性计算等内容。书中包含大量的实例和习题,注重程序测试、程序证明和问题求解,易......一起来看看 《Haskell函数式编程基础》 这本书的介绍吧!