可爱的Python编程_第1页
可爱的Python编程_第2页
可爱的Python编程_第3页
可爱的Python编程_第4页
可爱的Python编程_第5页
已阅读5页,还剩81页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

可爱的Python,Python技术前景开始使用PythonPython中的数据类型Python中的变量Python中的控制语句Python中的函数Python中的类,Python对象的序列化Python中的正则表达式Python多线程编程Python中的socket编程Python设计模式更可爱的yield,CONTENT,目录,什么是PythonPython技术优势Python的应用,CONTENT,1,Python技术前景,Python是一种功能强大的解释性,交互性,面向对象(OO)的第四代计算机编程语言。她集成了模块、包、例外机制、动态造型以及非常高级的动态数据类型。它的语法表达优美易读。它具有很多优秀的脚本语言的特点:解释的,面向对象的,内建的高级数据结构,支持模块和包,支持多种平台,可扩展。而且它还支持交互式方式运行,图形方式运行。它的语法有很多与众不同的特性。它具有动态语义和快速的原型开发能力,也许在短短的几分钟内,你就可以开发出使用其它语言可能需要花费几个小时的原型系统。Python丰富的工具集使得它位于传统脚本语言(如Tcl、Perl和Scheme)和系统编程语言(如C、C+和Java)之间,既具备了脚本语言的简单易用性,同时又能够提供只有系统语言才可能拥有的某些高级特性。,什么是Python,Python技术优势,容易学习,Python提供了一个交互式环境,这是他容易学习的主要原因之一,正如一个资深程序员所说,软件的复杂是因为千万件事堆在一起,交互式环境恰好可以让我门把程序分解开,我们可以试验每个不清楚的语言成分,同时这也是一个很好的测试平台。其次,Python程序很容易阅读。这得益于他的语法简洁,用缩排格式代替了,程序短小精悍(比其它语言,例如Java的代码短2/3到3/4),同时语言直截了当,接近自然语言,很少有专门定义的特殊符号,这也是Python容易学习的原因之一。,Python技术优势,火力强大,容易学习并不代表功能简单,从桌面程序,到网络互联,图形处理,科学计算,实时控制,到处都有Python的身影,Python是编译执行的,跨平台的(Windows,Unix,Macantoshi),面向对象的。Java可以完成的功能,Python都可以替代之。此外,支持类和多继承的面向对象程序设计,代码可以被打包为模块和包。支持异常处理追踪并能够列出比较清晰,详细的错误提示。包含了一些高级的程序设计特性,例如代码生成器和解释器,自动垃圾收集功能使你从内存管理的争战中解脱出来。庞大的标准库支持很多一般的程序设计任务,如网络服务器连接,正则表达式,文件操作,编译器很容易扩展,可以将C/C+编译后的摸板作为新的摸板加入到其中。,Python技术优势,快速开发,Python内建的高层次数据结构,以及动态类型和动态邦定,使得它非常适合于快速应用开发,也适合于连接已有的部件。Python的简单易于阅读的语法强调了可读性,因此降低了程序的维护费用,Python支持模块和包,并鼓励程序模块化和代码重用。,高效运行,Python可以编译执行,其运行效率接近C语言的运行速度,相同功能的代码运行速度约为C的90%,而同时Java的运行速度却只能达到C的50%。,Python的流行程度,Python对国内的用户也许比较陌生,但在国外早已得到成熟、广泛的应用。著名的搜索引擎google,其核心代码就是用Python完成的,迪斯尼公司的动画生成,许多unix的版本(包括Linux)都内建了Python环境支持。就连google本身也是由Python技术建立的。,Python的应用,在许多领域都有Python的用武之地。包括桌面应用、科学计算、图形技术、动画、游戏、WEB应用、嵌入式系统等等,目前成功一些成功应用有:,Google核心搜索引擎美国宇航局使用Python实现CAD/CAE/PDM库及模型管理系统全球知名的光影技术先驱IndustrialLightg_list=orgA,orgB,orgC;printg_str;printg_list;defprint_org():print=beginprint_org;printg_str;printg_list;print-endprint_org;,文件main.py的内容:fromincimport*defprint_main():print+beginprint_mainprintg_str;printg_list;print-endprint_mainprint_org();print_main()g_str=main;g_list0=main;print_org();print_main();g_list=dddprint_org();print_main(),运行:E:pythonpythonmain.py结果:orgorgA,orgB,orgC=beginprint_orgorgorgA,orgB,orgC-endprint_org+beginprint_mainorgorgA,orgB,orgC-endprint_main=beginprint_orgorgmain,orgB,orgC-endprint_org+beginprint_mainmainmain,orgB,orgC-endprint_main=beginprint_orgorgmain,orgB,orgC-endprint_org+beginprint_mainmainddd-endprint_main,文件间的变量处理,if叙述for叙述break及continue叙述pass叙述while叙述try.except叙述特殊的yield,5,Python中的控制语句,if叙述,大概最为人所知的statement就是if叙述了,举例如下:x=int(raw_input(Pleaseenteranumber:)ifx#Measuresomestrings:.a=cat,window,defenestrateforxina:.printx,len(x).cat3window6defenestrate12,在循环的执行之中改变sequence的内容是危险的一件事(当然,只有可变的sequence像list才能作更动),如果你真的需要在循环的执行中改变list的成员值,最好先复制一份这个list的拷贝,然后针对这个拷贝来做循环。list的切割(slice)提供了一个简便的制作拷贝的方法:forxina:#makeaslicecopyoftheentirelist.iflen(x)6:a.insert(0,x).adefenestrate,cat,window,defenestrate,break及continue叙述,forninrange(2,10):.forxinrange(2,n):.ifn%x=0:.printn,equals,x,*,n/x.break.else:.printn,isaprimenumber.,如同在C语言里一样,break叙述中断最靠近的一个for或while循环。同样的,从C语言借过来的continue叙述会中断目前执行的循环,并且执行下一个循环。特别的是,Python的循环有一个else子句,这个子句之后的程序代码会在整个循环正常结束的时候执行,(对for)循环而言指的是list已经到底,对while循环而言指的是条件式变成false)。但是,若是在非正常结束(因为break叙述)的情况下else子句的程序代码就不会执行。底下的例子是一个循环,用来找出所有的质数:,2isaprimenumber3isaprimenumber4equals2*25isaprimenumber6equals2*37isaprimenumber8equals2*49equals3*3,pass叙述,pass叙述什么也不做,通常是用在当你的程序的语法上需要有一个叙述,但是却不需要做任何事的时候。例子如下:while1:.pass#Busy-waitforkeyboardinterrupt.程序在设计阶段,把一些类、函数、接口等都定义好,但是还没有实现的情况下,一般用pass表示,如下:classCBaseOpt:.pass.deffun():.pass,while叙述,在这个程序中,首先,我们检验变量running是否为True,然后执行后面的while-块。在执行了这块程序之后,再次检验条件,在这个例子中,条件是running变量。如果它是真的,我们再次执行while-块,否则,我们继续执行可选的else-块,并接着执行下一个语句。当while循环条件变为False的时候,else块才被执行这甚至也可能是在条件第一次被检验的时候。如果while循环有一个else从句,它将始终被执行,除非你的while循环将永远循环下去不会结束!,number=23running=Truewhilerunning:guess=int(raw_input(Enteraninteger:)ifguess=number:printCongratulations,youguessedit.running=False#thiscausesthewhilelooptostopelifguesstry:.open(myfile.txt).read().exceptIOError,(errno,strerror):.printI/Oerror(%s):%s%(errno,strerror).exceptValueError:.printCouldnotconvertdatatoaninteger.except:.printUnexpectederror:,sys.exc_info()0.raise.else:.printnoexcept!.I/Oerror(2):Nosuchfileordirectory,try.except的叙述有一个可有可无的else子句(elseclause)可以使用,当这个子句存在时,必须是放在所有的exceptclauses的后面。这个子句里的叙述是当try子句没有发生任何exception时,一定要执行的叙述,except可以嵌套,不过一般是外面的比里面的要大,比如except:就包含了所有的异常。,tryexcept叙述,try:.open(myfile.txt).read().finally:.printfinally!.发生异常后,也会保证finally里的语句会执行。运行结果:finally!Traceback(mostrecentcalllast):File,line2,in?IOError:Errno2Nosuchfileordirectory:myfile.txt,特殊的yield,后续会详细介绍,这是个好东东,也是Python的一大特性。,函数的定义函数的参数函数的自省函数的作用域嵌套函数,CONTENT,6,Python中的函数,函数的定义,函数是重用的程序段。它们允许你给一块语句一个名称,然后你可以在你的程序的任何地方使用这个名称任意多次地运行这个语句块。这被称为调用函数。我们已经使用了许多内建的函数,比如len和range。函数通过def关键字定义。def关键字后跟一个函数的标识符名称,然后跟一对圆括号。圆括号之中可以包括一些变量名,该行以冒号结尾。接下来是一块语句,它们是函数体。如下简单函数:,defsayHello():printHelloWorld!#blockbelongingtothefunctionsayHello()#callthefunction,函数的参数,函数形参形参是函数的参数名称。如a、b,函数实参提供给函数调用的值为实参。如3、4、x、y;在第一个printMax使用中,我们直接把数,即实参,提供给函数。在第二个使用中,我们使用变量调用函数。printMax(x,y)使实参x的值赋给形参a,实参y的值赋给形参b。,defprintMax(a,b):ifab:printa,ismaximumelse:printb,ismaximumprintMax(3,4)x=5y=7printMax(x,y),deffunc(a,b=5,c=10):printais,a,andbis,b,andcis,cfunc(3,7)func(25,c=24)func(c=50,a=100),在第一次使用函数的时候,func(3,7),参数a得到值3,参数b得到值7,而参数c使用默认值10。在第二次使用函数func(25,c=24)的时候,根据实参的位置变量a得到值25。根据命名,即关键参数,参数c得到值24。变量b根据默认值,为5。在第三次使用func(c=50,a=100)的时候,我们使用关键参数来完全指定参数值。注意,尽管函数定义中,a在c之前定义,我们仍然可以在a之前指定参数c的值。,名为func的函数有一个没有默认值的参数,和两个有默认值的参数。,函数的参数,如果用过C语言中的printf(),那么就会对参数个数可变的意义比较了解。在Python中*表示接受任意多个参数,除了前面的参数后,多余的参数都作为一个tuple传递给函数printf,可以通过arg来访问。,defprintf(format,*arg):.printformat%arg.printf(%disgreaterthan%d,1,2)1isgreaterthan2,defprintf(format,*keyword):.forkinkeyword.keys():.printkeyword%sis%s%(k,keywordk).printf(ok,One=1,Two=2,Three=3)keywordThreeis3keywordTwois2keywordOneis1,还可以把这两中机制和可选参数机制合在一起使用。函数接受参数的顺序,先接受固定参数,然后是可选参数,然后是接受任意参数,最后是带名字的任意参数。,还有种形式可以实现任意多个参数,就是按照dictionary方式传递给函数。同上一种机制,只不过*keyword是用*表示接受任意多个有名字的参数传递,调用时要指定参数的名字,如One、Two、Three等。,deftestfun(fixed,optional=1,*arg,*keywords):.printfixedparametersis,fixed.printoptionalparameteris,optional.printArbitraryparameteris,arg.printkeywordsparameteris,keywords.testfun(1,2,a,b,c,one=1,two=2,three=3)fixedparametersis1optionalparameteris2Arbitraryparameteris(a,b,c)keywordsparameteristhree:3,two:2,one:1,函数的自省,defprintMax(x,y):Printsthemaximumoftwonumbers.Thetwovaluesmustbeintegers.x=int(x)#converttointegers,ifpossibley=int(y)ifxy:printx,ismaximumelse:printy,ismaximumprintMax(3,5)printprintMax._doc_,5ismaximumPrintsthemaximumoftwonumbers.Thetwovaluesmustbeintegers.,运行后的输出:,在函数的第一个逻辑行的字符串是这个函数的文档字符串。注意,自省也适用于模块和类。文档字符串的惯例是一个多行字符串,它的首行以大写字母开始,句号结尾。第二行是空行,从第三行开始是详细的描述。可以使用_doc_(注意双下划线)调用printMax函数的文档字符串属性。请记住Python把每一样东西都作为对象,包括这个函数。自动化工具也可以从程序中提取文档。因此,强烈建议所写的任何正式函数编写文档字符串。随着Python发行版附带的pydoc命令,与help()类似地使用DocStrings。,函数的作用域,Python按照LGB规则找变量,先找localnamespace(局部命名空间),再找globalnamespace(全局命名空间),然后再找buildinnamespace(内在命名空间)用global语句可以改变某些变量的命名空间。,a=1deftestfun():.a=2.printa.testfun()2a1,a=1deftestfun():.globala.a=2.printa.testfuntestfun()2a2,函数testfun()中的a是localnamespace中,修改a不会改变globalnamespace中的a但是,用global语句可以修改一个变量的所在的namespace。,嵌套函数,defoutfun(a,b):.definnerfun(x,y):.returnx+y.returninnerfun(a,b).outfun(1,2)3,这个在C语言是不容许的,因为C中的static函数可以替代这种功能。这种机制提供了一个函数范围的概念,某些函数只在某些函数的内部,才看得到,如果要公开,可以通过返回值,将内部函数返回。注意,嵌套函数不能访问外层函数的变量。,类定义类/类实例属性类继承类中的一些特殊方法重载特殊方法用法举例,CONTENT,7,Python中的类,类的定义,classPerson:#def_init_(self,name):#=name#defsayHi(self):#printHello,mynameis,p=Person(Swaroop)p.sayHi(),类的方法与普通的函数只有一个特别的区别它们必须有一个额外的第一个参数名称,但是在调用这个方法的时候你不为这个参数赋值,Python会提供这个值。这个特别的变量指对象本身,按照惯例它的名称是self。Python中的self等价于C+中的self指针和Java、C#中的this参考。为何不需要给self赋值。举一个例子会使此变得清晰。假如你有一个类称为MyClass和这个类的一个实例MyObject。当你调用这个对象的方法MyObject.method(arg1,arg2)的时候,这会由Python自动转为MyClass.method(MyObject,arg1,arg2)这就是self的原理了。这也意味着如果你有一个不需要参数的方法,你还是得给这个方法定义一个self参数。,我们使用class语句后跟类名,创建了一个新的类。这后面跟着一个缩进的语句块形成类体。_init_方法在类的一个对象被建立时,马上运行。这个方法可以用来对你的对象做一些你希望的初始化。是成员变量。sayHi是成员方法。,类/类实例属性,对象的变量由类的每个对象/实例拥有。因此每个对象有自己对这个域的一份拷贝,即它们不是共享的,在同一个类的不同实例中,虽然对象的变量有相同的名称,但是是互不相关的。通过一个例子会使这个易于理解。,Python分类的变量和对象的变量,它们根据是类还是对象拥有这个变量而区分。,类的变量由一个类的所有对象(实例)共享使用。只有一个类变量的拷贝,所以当某个对象对类的变量做了改动的时候,这个改动会反映到所有其他的实例上。Python利用这个实现了C+中的静态成员变量,就是同一个class的不同instance共享同一个变量。,类/类实例属性,运行结果:,classPerson:population=0def_init_(self,name):=nameprint(Initializing%s)%Person.population+=1def_del_(self):print%ssaysbye.%Person.population-=1ifPerson.population=0:printIamthelastone.else:printTherearestill%dpeopleleft.%Person.populationdefsayHi(self):printHi,mynameis%s.%defhowMany(self):ifPerson.population=1:printIamtheonlypersonhere.else:printWehave%dpersonshere.%Person.population,swaroop=Person(Swaroop)swaroop.sayHi()swaroop.howMany()kalam=Person(AbdulKalam)kalam.sayHi()kalam.howMany()swaroop.sayHi()swaroop.howMany(),(InitializingSwaroop)Hi,mynameisSwaroop.Iamtheonlypersonhere.(InitializingAbdulKalam)Hi,mynameisAbdulKalam.Wehave2personshere.Hi,mynameisSwaroop.Wehave2personshere.AbdulKalamsaysbye.Therearestill1peopleleft.Swaroopsaysbye.Iamthelastone.,类继承,对于继承和C+一样,只是比C+中的继承更简单,没有了一堆什么私有公有继承。,classSchoolMember:def_init_(self,name,age):=nameself.age=ageprint(InitializedSchoolMember:%s)%deftell(self):printName:%sAge:%s%(,self.age),classTeacher(SchoolMember):def_init_(self,name,age,salary):SchoolMember._init_(self,name,age)self.salary=salaryprint(InitializedTeacher:%s)%deftell(self):SchoolMember.tell(self)printSalary:%d%self.salaryclassStudent(SchoolMember):def_init_(self,name,age,marks):SchoolMember._init_(self,name,age)self.marks=marksprint(InitializedStudent:%s)%deftell(self):SchoolMember.tell(self)printMarks:%d%self.marks,t=Teacher(Mrs.Shrividya,40,30000)s=Student(Swaroop,22,75)print#printsablanklinemembers=t,sformemberinmembers:member.tell(),(InitializedSchoolMember:Mrs.Shrividya)(InitializedTeacher:Mrs.Shrividya)(InitializedSchoolMember:Swaroop)(InitializedStudent:Swaroop)Name:Mrs.ShrividyaAge:40Salary:30000Name:SwaroopAge:22Marks:75,运行结果:,Python和JAVA一样也支持多重继承,这里不介绍了。,类中的一些特殊方法,Class中有很多的特殊方法,像前面讲的_init_就是其中一个,下面我们再列举几个:,_init_前面已经介绍,就是在对象创建时被自动调用,用于初试化;_del_前面也介绍了,在对象删除时被自动调用,可以做些我们的收尾工作;_repr_使用repr(obj)时自动调用,返回和eval()兼容的对象字符串eval(repr(obj);_str_使用str(obj)时自动调用,返回对象的字符串描述;_cmp_比较操作符,0表示相等,1表示大于,-1表示小于;_hash_返回一个32位的hashvalue,一般将对象hash后用作dictionary的key;_nozero_定义对象是否是逻辑假,返回0表示逻辑假,返回1表示逻辑真;_len_使用len(obj)时自动调用,返回对象的长度;_getitem_返回selfkey用来模拟list、dictionary等数据结构;_setitem_设置selfkey,模拟selfkey=value;_delitem_模拟delselfkey,调用这个函数;_contain_可以使对象像队列一样,处理in语句;_call_使对象像函数一样,可以调用,如obj(arg)。,重载特殊方法用法举例,重载_setattr_实现只读属性:,classA:readonlyValue=100def_setattr_(self,attr,value):ifattr=readonlyValue:raisecannotchangethereadonlyvalue“a=A()printa.readonlyValuea.readonlyValue=102,在给对象某个set值时会自动调用_setattr_,接受的参数分别是,对象本身(self),attribute的名字(attr),和要设的值(value)。那么重载_setattr_就可以实现我们想保护的属性。,运行结果:,100Traceback(mostrecentcalllast):Filereadonlyattr.py,line12,in?a.readonlyValue=102Filereadonlyattr.py,line7,in_setattr_raisecannotchangethereadonlyvaluecannotchangethereadonlyvalue,重载特殊方法用法举例,重载_getattr_实现对象组合:,classB:defprintMe(self):printIamBdefprintOk(self):printBsay:OKclassC:defprintMe(self):printIamCdefprintOk(self):printCsay:OKclassA:_realobj_=B()def_getattr_(self,attr):returngetattr(self._realobj_,attr)defprintMe(self):printIamA“a=A()a._realobj_=B()a.printMe()a.printOk()a._realobj_=C()a.printMe()a.printOk(),实现_getattr_,可以通过组合对象的方法,代替继承机制。类继承和组合对象是面向对象的两种常用复用代码的方式,但是有个原则:优先使用组合,而不是继承。这个例子就是利用attribute的搜索算法,_getattr_是最后一步,也就是说如果在自身对象或者直接/间接的对象中找不到某个属性,那么就会通过_getattr_转嫁到_realobj_上了,从而实现对象的组合。,IamABsay:OKIamACsay:OK,运行结果:,重载特殊方法用法举例,利用setattr为对象动态增加attribute:,classA:def_init_(self,*kws):fork,vinkws.items():setattr(self,k,v)defDumpObj(self):fork,vinvars(self).items():print%10s:%s%(k,v)D=one:1,two:2,three:3a=A(five=5,six=6)fork,vinD.items():setattr(a,k,v)DumpObj(a),从这个例子看出,其实一个对象也就是一个dicationary的高级数据结构。,one:1six:6five:5three:3two:2,运行结果:,重载特殊方法用法举例,对象工厂实现:,classObjFactory:def_init_(self,clsobj=None,*args,*keyargs):self.clsobj=clsobjandclsobjorself._class_self.args=argsself.keyargs=keyargsdefcreateObj(self):returnself.clsobj(*self.args,*self.keyargs)classtestClass:def_init_(self,value1,value2,*args,*keyargs):fork,vinkeyargs.items():setattr(self,k,v)self.args=argsself.value1=value1self.value2=value2defDumpObj(self):fork,vinvars(self).items():print%10s:%s%(k,v)f=ObjFactory(testClass,100,200,300,one=1,two=2,three=3)DumpObj(f.createObj(),对象工厂是生产对象的地方,在C+中,为了灵活的生成不同的对象,采用了很多办法,在Python中更简单,表达更加紧凑,原因就是在Python中class本身就是一个对象。,one:1value2:200value1:100args:(300,)three:3two:2,运行结果:,CONTENT,8,Python对象的序列化,CONTENT,9,Python中的正则表达式,线程对象简单的线程同步同步队列,CONTENT,10,Python多线程编程,线程对象,要创建一个线程对象,很简单,只要你的类继承threading.Thread,然后在_init_里首先调用threading.Thread的_init_方法,重写类的run()方法即可,把你要在线程执行时做的事情都放到里面,一切就是这么简单。,classmythread(threading.Thread):def_init_(self,threadname):threading.Thread._init_(self,name=threadname)defrun(self):foriinrange(10):printself.getName,itime.sleep(1),mythread1=mythread(mythread1)mythread1.start(),使用:,简单的线程同步,“锁”。锁对象用threading.RLock类创建,mylock=threading.RLock(),mylock=threading.RLock()classmythread(threading.Thread).defrun(self.):.#此处不可以放置修改共享数据的代码mylock.acquire().#此处可以放置修改共享数据的代码mylock.release().#此处不可以放置修改共享数据的代码,条件变量是如何工作的呢?首先一个线程成功获得一个条件变量后,调用此条件变量的wait()方法会导致这个线程释放这个锁,并进入“blocked”状态,直到另一个线程调用同一个条件变量的notify()方法来唤醒那个进入“blocked”状态的线程。如果调用这个条件变量的notifyAll()方法的话就会唤醒所有的在等待的线程。,条件变量。用threading.Condition类创建,mycondition=threading.Condition(),同步队列,#ProducerthreadclassProducer(threading.Thread):def_init_(self,threadname,queue):threading.Thread._init_(self,name=threadname)self.sharedata=queuedefrun(self):foriinrange(20):printself.getName(),adding,i,toqueueself.sharedata.put(i)time.sleep(random.randrange(10)/10.0)printself.getName(),Finished#ConsumerthreadclassConsumer(threading.Thread):def_init_(self,threadname,queue):threading.Thread._init_(self,name=threadname)self.sharedata=queuedefrun(self):foriinrange(20):printself.getName(),gotavalue:,self.sharedata.get()time.sleep(random.randrange(10)/10.0)printself.getName(),Finished#Mainthreaddefmain():queue=Queue()producer=Producer(Producer,queue)consumer=Consumer(Consumer,queue),示例代码中实现了两个类:生产者类Producer和消费者类Consumer。前者在一个随机的时间内放入一个值到队列queue中然后显示出来,后者在一定随机的时间内从队列queue中取出一个值并显示出来。,printSducer.start()consumer.start()producer.join()consumer.join()printAllthreadshaveterminated.,运行结果:,CONTENT,11,Python中的socket编程,Python与设计模式单体模式SimpleFactory模式FactoryMethod模式AbstractFactory模式,CONTENT,12,Python设计模式,Python与设计模式,尽管设计模式的目标是努力做到与语言的无关性,但事实上许多模式在应用时还是需要依赖于具体实现语言的某些特性,尤其是该语言的对象模型。在Python中应用设计模式的一个有利因素是它的动态类型绑定,也就是说一个对象很少只是一个类的实例,而是可以在运行时动态改变。在面向对象系统中,接口是一个基本的组成部分,对象只有通过它们的接口才能与外界进行交互。对象的接口与其功能是完全分离的,支持相同请求的不同对象针对同一请求所触发的操作可能完全不同,这就是动态绑定的概念。动态绑定虽然看起来在一定程度上使得代码不同那么容易理解和维护,但它的确可以使整个软件系统的结构显得更加清晰和合理。后续我们简单介绍下创建型设计模式,重在描述用Python来实现,至于这个设计模式的好处和为什么非要用这个模式,大家看过设计模式相关资料的都知道,这里就不说明了。,单体模式,单体是保证在程序运行中,只存在一个实例。Python中单体可以这样来实现:,文件:singleton.pyclassSingleton(object):_instance=Nonedef_new_(cls,*args,*kwargs):ifnotcls._instance:cls._instance=super(Singleton,cls)._new_(cls,*args,*kwargs)returncls._instance,文件:mysingleton.pyclassMySingletom(Singleton):_att=def_init_(self,att):ifnotself._att:self._att=attdefGetatt(self):returnself._att,运行:obj1=MySingletom(obj1)obj2=MySingletom(obj2)id(obj1),id(obj2)(10049912,10049912)obj1.Getatt(),obj2.Getatt()(obj1,obj1),SimpleFactory模式,简单工厂模式属于类的创建型模式,适合用来对大量具有共同接口的类进行实例化,它可以推迟到运行的时候才动态决定要创建哪个类的实例,而不是在编译时就必须知道要实例化哪个类。简单工厂模式的一般性结构如图所示:,SimpleFactory模式,文件:creator.pyclassShapeFactory:#创建具体产品类的方法deffactory(self,which):ifwhich=Circle:returnCircle()elifwhich=Rectangle:returnRectangle()elifwhich=Diamond:returnDiamond()else:returnNone,文件:shape.pyclassShape:#所有具体产品类的公共接口defdraw(self):pass,文件:shape.pyclassCircle:#绘制圆形defdraw(self):pass,文件:shape.pyclassRectangle:#绘制矩形defdraw(self):pass,文件:shape.pyclassDiamond:#绘制菱形defdraw(self):pass,文件:main.pyfac=ShapeFactory()Shape=fac.factory(Diamond)ifshape!=None:shape.draw(),将类是如何创建的这一实现细节向外界隐藏起来了,这就是简单工厂模式所采取的基本策略,FactoryMethod模式,工厂方法模式是简单工厂模式的进一步抽象和推广,它不仅保持了简单工厂模式能够向客户隐藏类的实例化过程这一优点,而且还通过多态性克服了工厂类过于复杂且不易于扩展的缺点。在工厂方法模式中,处于核心地位的工厂类不再负责所有产品的创建,而是将具体的创建工作交由子类去完成。工厂方法模式中的核心工厂类经过功能抽象之后,成为了一个抽象的工厂角色,仅负责给出具体工厂子类必须实现的接口,而不涉及哪种产品类应当被实例化这一细节。工厂方法模式的实质是将对象的创建延迟到其子类实现,即由子类根据当前情况动态决定应该实例化哪一个产品类,FactoryMethod模式,工厂方法模式的一般性结构如图所示,图中为了简化只给出了一个产品类和一个工厂类,但在实际系统中通常需要设计多个产品类和多个工厂类,后续我们以一个实例来说明。,FactoryMethod模式,个人信息管理系统(PIM),它可以保存日常工作和生活中所需的各种信息,包括地址本、电话簿、约会提醒、日程安排等等。很显然,PIM的用户界面的设计将是比较复杂的,因为必须为每种信息的输入、验证和修改都提供单独的界面,以便同用户进行交互。在具体实现时可以设计一个通用接口Editable,并且让所有处理特定个人信息(如通信地址和电话号码)的用户界面都继承于它,而PIM则通过Editable提供的方法getEditor()获得Editor的一个实例,并利用它来对用户输入进行统一的处理。例如,当用户完成输入之后,PIM可以调用Editor中的方法getContent()来获取用户输入的数据,或者调用resetUI()来清除用户输入的数据。在采用这一体系结构之后,如果要扩展PIM的功能,只需添加与之对应的Editable和Editor就可以了,而不用对PIM本身进行修改。,FactoryMethod模式,FactoryMethod模式,文件:editable.pyclassEditable:个人信息用户界面的公共接口“#获得个人信息编辑界面defgetEditor(self):returnself.editor,文件:editor.pyclassEditor:用户使用特定的Editor来编辑个人信息#获取代表用户界面(UI)的对象defgetUI(self):pass#获取用户输入的数据defgetContent(self):pass#提交用户输入的数据defcommitChanges(self):pass#清空用户输入的数据defresetUI(self):pass,文件:editableaddress.pyclassEditableAddress(Editable):用于处理个人地址信息的Editable#构造函数def_init_(self,master):self.editor=AddressEditor(self)classAddressEditor(Editor,Tkinter.Frame):用于处理个人地址信息的Editor“#构造用户界面defcre

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论